#clojure log - Dec 27 2010

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

0:00 qbg: And also for the fact that they queue up actions

0:00 Guest32627: qbg: i guess combined with an error handler on your agent to make sure errors get logged to, that works pretty well

0:01 qbg: sure, the queueing is a necessary part of the asynchronous processing. just like an MDB :)

0:01 well... one attached to a queue anyway, not a topic :D

0:03 qbg: Hmm... Not sure if I'll be able to add some basic syntax-class support to my syntax-rules/syntax-parse mashup tonight

0:08 Binding *ns* in a test feels nasty

2:17 killy971: Hello, I'm looking for some help on macros. I would like to make a factorial function with pre-calculated results (for just a few values). I got some help a while back, and have the following piece of code:

2:17 (defn static-fact [digit] (let [x 'x] `(case ~x ~@(mapcat (juxt identity fact) (range (inc digit))))))

2:17 (static-fact 10) yields the following result in the repl: (clojure.core/case x 0 1 1 1 2 2 3 6 4 24 5 120 6 720 7 5040 8 40320 9 362880 10 3628800)

2:17 What I would like then is to make a function/macro from this result.

2:18 (given that I have already defined the fact function)

2:20 tomoj: killy971: the reason is that you will be calling static-fact ofter with low values?

2:20 s/ofter/often

2:20 sexpbot: <tomoj> killy971: the reason is that you will be calling static-fact often with low values?

2:20 killy971: yes

2:20 actually just digits

2:20 tomoj: have you considered memoize?

2:21 killy971: but I was wondering how to write some clever static code, instead of memoized or verbose long case

2:21 tomoj: oh, just to try it out?

2:21 killy971: yes, I have never really used macros until now, so I thought it could be a good occasion

2:25 I don't really understand how to stick my code in the definition of a function "digit-fact", which could be used like this: (digit-fact 3)

2:29 tomoj: I think you're right that this is a nice simple experiment

2:29 but my brain isn't working right now

2:29 have you ever used defmacro before?

2:30 I mean, successfully, at all?

2:30 Scriptor: macros are fun

2:31 killy971: what exactly are you trying to do?

2:31 killy971: tomoj: I mean, successfully, at all?> just read stuart holloway book

2:32 Scriptor> writing a succinct factorial function with pre-computed results (for digits)

2:33 so I would like to use the macro facility to generate the part (case 1 1 2 2 3 6 4 24 ...)

2:33 I already have the following piece of code : (defn static-fact [digit] (let [x 'x] `(case ~x ~@(mapcat (juxt identity fact) (range (inc digit))))))

2:34 it yields the case part if I execute it in the repl like this (static-fact 10)

2:34 tomoj: clojurebot: hygiene?

2:34 clojurebot: Cool story bro.

2:40 tomoj: huh

2:40 wow

2:43 killy971: any idea of how to do this?

2:43 tomoj: well

2:43 I have a gist with a shitty answer

2:44 https://gist.github.com/f04db48b5f33d4810de2

2:44 sticking (range n) and (resolve f) in there seems wrong to me

2:46 killy971: I'm looking at the code

2:48 great, it works as expected. but why do you say (range n) and (resolve f) seems wrong?

2:49 tomoj: just seems odd

2:49 also, suppose I want to caseify not with a range from 0 but with some other seq of input vals

2:49 amalloy: tomoj: resolve definitely seems like it shouldn't be necessary; i agree about range

2:49 tomoj: I tried that originally, but you'd have to eval the form they pass in or something.. ugly

2:50 amalloy: instead of n, accept a seq

2:50 killy971: oh if you mean this

2:50 ok

2:50 tomoj: amalloy: yeah.. and do what with it? it's a macro

2:50 amalloy: oh, hm

2:51 tomoj: if it's a vector, you'd want to just go with those vals. if a list, eval would get you the right answer, but..

2:51 list or symbol, I guess..

2:55 killy971: thank you for the gist, at least it solves my prob

4:03 zvrba: hmm, how does equality work in clojure? what semantics does = have, when compared to CL? eq? eql? equal?

4:03 ah, found it in the docs: it's value comparison.

4:04 but given that data structures are immutable, is "value" comparison in this case implemented as identity comparison?

8:03 mrSpec: Hello! Could you tell me why (let [h my-hashmap] ...) is working, but (let [h (eval (read-from-string "my-hashmap"))]...) is not? this eval seems to work in REPL but not in the function :(

8:14 Chousuke: mrSpec: eval can't access locals. what is it that you're actually evaling?

8:14 mrSpec: it is global hashmap

8:15 (def hash (new java.util.LinkedHashMap))

8:15 Chousuke: also, what is the error?

8:16 mrSpec: here is the problem... I cant see the error, Jslider is just not working

8:16 Chousuke: hmh

8:16 your problem is probably using eval in the first place :P

8:16 mrSpec: ok I've used (if ...) instead of eval...

8:17 Chousuke: but I can't really suggest anything better since I don't know what you're trying to do.

8:17 mrSpec: ok

8:17 unfortunately i'm in rush. so I'll ask about this later, and tell more :)

10:43 chouser: ugh. maven fail. http://tinyurl.com/2b6azmz

11:51 drewolson: hey all. suppose i wanted to store a java.util.Random in a ref and call the .nextInt function on it inside a dosync. I'm assuming simply calling (dosync (.nextInt @*rand*)) will not actually be synchronous because i'm not using alter or commute. is this correct?

11:52 qbg: It will be executed

11:52 But .nextInt has side effects, so you shouldn't use it in a dosync

11:53 Why do you want to use dosync here?

11:53 drewolson: qbg: i want to ensure multiple threads can generate distinct random numbers. i may be completely off here.

11:54 qbg: Isn't .nextInt already synchronized?

11:54 drewolson: qbg: it may well be, i'm not sure.

11:54 qbg: No

11:55 Doesn't appear to be

11:55 drewolson: qbg: so i'd like to access it sychronously, but i'm not sure how to do that using alter/commute.

11:56 qbg: Sounds like (locking @*rand* (.nextInt @*rand*)) should work

11:56 drewolson: qbg: i'll look into locking, thanks for the help

11:56 qbg: But there is little reason to have a Random in a ref

11:57 Another thought: why share the one random object between multiple threads?

11:58 drewolson: qbg: i probably won't eventually, i just became curious about accessing a java instance concurrently with methods with side effects.

11:58 qbg: The STM only works on refs, not java objects

11:59 drewolson: qbg: great, thanks for the help

12:19 amalloy: drewolson: i agree with qbg that locking is probably the best choice here, but you might be interested in java.lang.ThreadLocal for other, similar things

12:32 LauJensen: ,(str (java.util.UUID/randomUUID))

12:32 clojurebot: "fee8a2e9-b286-40fb-a9be-bac7c8ba3fb3"

12:32 LauJensen: drewolson: If you dont specifically need an int, the above will guarantee a unique return on each call. If you need an int, call hash on the result

12:33 No locks, no nothing

12:38 amalloy: Did you catch that? :)

12:39 amalloy: LauJensen: heh. that's an amusing use of uuids

12:39 LauJensen: amalloy: its called: creative

12:39 amalloy: ah, of course. that's what i meant. creative

12:55 drewolson: amalloy, LauJensen: thanks for your help

12:56 LauJensen: np

13:49 dnolen: qbg: yeah *file* + &form is enough I think. Now I'm excited :D

13:50 syntax-rulez!

13:51 cemerick: I did as well. But once you've internalized CL style macros. syntax-rules sounds like heaven. It's much less noisy and covers the common cases.

13:51 qbg: They only look hard :)

13:52 cemerick: dnolen: Perhaps that's it -- the last time I used scheme in earnest, it was before I had properly grokked CL-style macros.

13:55 dnolen: the thing I like about syntax-rules is that it eliminates common cases that require splicing. You can specify patterns.

13:55 qbg: Just pushed out the line number stuff

13:55 dnolen: qbg: sweet

13:56 qbg: the moment you push a stable release to clojars, I'm going to replace my ugly logos.minikanren macros with syntax-rules :)

13:57 qbg: I also mailed my CA form today

13:59 The downside of the current error messages is that the filename and line number are part of the message, so you also have the filename and line number provided by the JVM which is separate...

13:59 I wonder if I could make that be correct instead...

14:01 Now I just need to implement guards and add a form for defining syntax classes

14:01 (and define a ton of built in syntax classes)

14:03 Is there a function that is equivalent to (first (filter ...))?

14:09 amalloy: qbg: i don't think so. there's (some), but that gets you (f x) instead of x

14:10 qbg: It seems like it could be a useful function to have (for communicating a concept)

14:11 amalloy: qbg: i agree. i've written (first (filter ..)) enough times that it ought to be abstracted out

14:12 qbg: What would it be called? some is already taken

14:26 dnolen: qbg: pick?

14:27 amalloy: qbg: (only even? (range))?

14:28 qbg: It should make sense in context of (if (<name> ...) <stuff to do if there is at least one such element>)

14:28 aqclj: hello

14:28 qbg: amalloy: only implies filter to me, not (first (filter ...))

14:29 pick might work, but I feel it is a bit lacking

14:30 find?

14:30 I think that is what it is called in CL

14:30 stuartsierra: `find` is taken

14:30 qbg: Oh, yes

14:31 It is called find-if in CL

14:31 Obvious: find-if

14:31 yep

14:32 qbg: Maybe find-pred?

14:32 Not as nice as a single word though...

14:32 amalloy: stuartsierra: since you mention it, why does find exist? it looks like get is a perfect drop-in substitute

14:33 stuartsierra: `find` returns the actual Map.Entry, not just the value.

14:36 aqclj: Hi, I have something like: (["x" LazySeq] ["x2" LazySeq] ...). I would like to get the first n bigger values from all the LazySeq. Any ideas?

14:36 LauJensen: Any brilliant webdesigners in here, who would like to contribute either a design or a mock for clojureql.org ?

14:37 qbg: aqclj: Could you give sample input and output?

14:37 aqclj: yes

14:38 the input would be the above sequence, and the LazySeqs are sequences of numbers

14:38 and as output I would like to have the number of times "x" got the bigger number, and so on

14:39 I know how to get the bigger value each time, but I don't know how to make the loop, and to select the next value in the LazySeq

14:41 qbg: I think I see what you want

14:42 stuartsierra: Use `map` to return a sequence of "x"s or "x2"s representing who had the bigger number each time. Then call `frequencies` on that result.

14:45 aqclj: thanks, I'm trying that now (I'm slow)

14:45 qbg: https://gist.github.com/756469 maybe?

14:45 (could be better)

14:47 Actually, that is going to be smallest...

14:47 Fixed

14:49 aqclj: the code got stuck, like in a infinite loop

14:49 maybe it's because my lazyseq has no ending :S

14:50 qbg: It does it for all values, not only the first n

14:50 fixed

14:51 That code could be much better

14:53 aqclj: thanks, I'm trying to understand it now. It seems that something goes wrong, but now it doesn't get stuck

14:53 qbg: It could be that I'm misunderstanding what exactly you want

14:55 aqclj: at each loop, the bigger value within all the lazyseqs should be replaced by the next in the sequence

14:55 Berengal: Does putting anything inside a do at the toplevel make a difference?

14:56 qbg: Berengal: I don't think so

14:56 aqclj: Is this for sorting or something?

14:57 (like a merge sort)

14:57 aqclj: more or less

14:57 for example

14:57 Berengal: qbg: Thanks

14:58 Also, what's the prefered idiom for updating a single value in a map/struct?

14:58 qbg: assoc

14:58 amalloy: Berengal: update-in

14:58 or assoc, depending

14:58 Berengal: amalloy: assoc makes a new entry, doesn't it?

14:58 amalloy: Berengal: overwriting any previous entry that was there

14:58 qbg: Yes, maps/structs are immutable

14:58 aqclj: if the lazyseq for "x1" is (10 8 4 2) and the lazyseq for "x2" is (33 9 2 1), and I ask for 3, I should get "x1" 1 and "x2" 2

14:59 qbg: aqclj: I would first write a function that returns a sequence of "x1"/"x2"/etc., then take n of them, and then pass that to frequencies

15:00 amalloy: so if you want to "update" the value to, say, 4, you should just (assoc m k 4); if you want to change the value based on its current value, you want (update-in m [k] function-of-value)

15:00 Berengal: qbg: That's okay. I don't want to mutate, I just want a slightly modified value, based on the previous value at an entry

15:00 amalloy: Thanks, that looks like it

15:00 qbg: ,(assoc {:a 1, :b 2} :a 5)

15:00 clojurebot: {:a 5, :b 2}

15:00 amalloy: &(update-in {:a 1, :b 2} [:a] inc)

15:00 sexpbot: ⟹ {:a 2, :b 2}

15:01 aqclj: qbg: but that it wouldn't be lazy, would it? At each loop I should only ask for the next value in the lazyseq that got the max value

15:02 or I am wrong? :S

15:02 qbg: aqclj: Define that function to use lazy-seq

15:02 And use recursion

15:03 aqclj: ok thanks, I will try that

15:05 qbg: aqclj: Updated the gist to have that function instead

15:05 (assumes the input is a map)

15:08 aqclj: thanks again, I'm trying it

16:04 DanielGlauser: /msg NickServ identify 1l2gbOGH

16:05 dakrone: DanielGlauser: time to change that password :)

16:05 DanielGlauser: Oh crap

16:05 I guess it is :)

16:05 qbg: What? I only see ********

16:05 ;)

16:08 Eww, I just used eval...

16:27 ngw: what libs are available for s3 and aws in general ?

16:28 cemerick: ngw: jclouds has the deepest support for aws AFAIK (and provides clojure wrappers for much of it)

16:29 disclaimer: I'm a contributor there

16:30 ngw: thanks

16:35 DanielGlauser: Phew, I changed my password

16:36 /msg NickServ identify abc123

16:40 qbg: lolz

16:42 Almost got guards ready for my syntax-rules/syntax-parse mashup. I just need to make sure that the code in the guards will be namespace properly

16:42 *namespaced

16:45 Hmm... Maybe binding *ns* around eval would be good enough

16:53 ngw: any suggestion about how to structure a project in clojure ?

16:53 I'm messing (and I mean it) with leinigen but coming from ruby/python it's kind of confusing

16:54 amalloy: ngw: cake is similar to leiningen but uses a little ruby underneath; not sure if that's helpful

16:54 ngw: for example I just discovered there's a -main function, something that none of the books I've read about clojure mentions it

16:55 amalloy: ngw: -main isn't special, per se. -foo is how to create a MyClass.foo() method when AOT compiling

16:56 pdk: yknow i should get around to installing cake or lein

16:56 though how is the installation process on windows

16:56 amalloy: but both of them have a project.clj file in the project root to do configuration and management, and you can find a reasonable reference to that file format at http://is.gd/jAFJV

16:58 aqclj: I have a sequence of maps called m, when use (into {} m) it only returns one of the maps. How could I get all the maps outside the sequence so I can use the merge-with function?

16:59 amalloy: &(apply into {} [{:a 1} {:b 2, :c 3}])

16:59 sexpbot: java.lang.IllegalArgumentException: Wrong number of args (3) passed to: core$into

17:00 amalloy: &(apply merge-with + [{:a 1} {:b 2, :a 3}])

17:00 sexpbot: ⟹ {:b 2, :a 4}

17:00 amalloy: aqclj: ^^

17:01 aqclj: amalloy: thanks a lot!

17:01 what the & do?

17:01 amalloy: aqclj: asks sexpbot to evaluate for me

17:02 aqclj: ah ok

17:02 Luyt_: is it possible to have clojurebot do a deathmatch with sexpbot?

17:05 &(println ",(doc doc)")

17:05 sexpbot: ⟹ ,(doc doc) nil

17:05 qbg: ,(println "&(println \"Foo\")")

17:05 clojurebot: &(println "Foo")

17:05 sexpbot: ⟹ Foo nil

17:06 qbg: Now to quine it...

17:06 Luyt_: qbg - Luyt: 1-0 !

17:06 I tried to fool sexpbot into luring clojurebot out, that failed, you tried it the other way, that worked.

17:07 qbg: Yeah, sexpbot is going to make this hard...

17:07 Luyt_: sexpbot's output always starts with ⟹ and as such can never get an answer out of clojurebot.

17:07 qbg: &(println "\n,(doc doc)")

17:07 sexpbot: ⟹ ,(doc doc) nil

17:07 Raynes: I've done my part. Any exploitation will be on clojurebot. Thus, I void all responsibility. ;)

17:07 amalloy: Luyt_: sexpbot was carefully designed to prevent this :P

17:07 Luyt_: Good thing ;-)

17:08 qbg: &@(future (println ",(doc doc)"))

17:08 sexpbot: ⟹ nil

17:08 Luyt_: Now, what if clojurebot responded to ",(...)" and sexpbot to ",,(...)" (note two comma's instead of one)

17:08 Raynes: amalloy: Haha "carefully designed". More like horribly designed until _ato broke it in every which way imaginable and forced me to fix it... carefully. :>

17:09 amalloy: Raynes: carefully designed /eventually/

17:09 Raynes: That

17:09 qbg: &(let [i *in*] @(future (binding [*in* i] (println ",(doc doc)"))))

17:09 sexpbot: ⟹ nil

17:09 Raynes: is better.

17:09 qbg: &(let [i *out*] @(future (binding [*out* i] (println ",(doc doc)"))))

17:09 sexpbot: ⟹ ,(doc doc) nil

17:09 Raynes: qbg: You can also experiment with sexpbot in PM or in #sexpbot

17:09 In case it gets too floody for #clojure.

17:10 * Raynes runs off to eat more chili.

17:11 Luyt_: First versions of my programs always look a bit clumsy. Only after reshaping them they become a bit elegant. Like a clump of clay you have to sculpt and refine.

17:11 qbg: sexpbot wins this round...

17:12 Lets not quine clojurebot...

17:21 jlaskowski: hi

17:21 I'm having troubles with java.lang.IllegalArgumentException: No matching method found: createInjector

17:22 CLASSPATH=`pwd`/guice/guice-3.0-rc1.jar:`pwd`/guice/javax.inject.jar:`pwd`/guice/aopalliance.jar clj -13

17:22 CLOJURE_DIR: /Users/jacek/apps/clojure

17:22 CLOJURE_CONTRIB_JAR: /Users/jacek/apps/clojure-contrib-1.3.0-alpha3.jar

17:22 Clojure 1.3.0-alpha4

17:22 (def mm (proxy [AbstractModule] [] (configure [] (println "configure called"))))

17:22 (bean mm)

17:22 {:class user.proxy$com.google.inject.AbstractModule$0}

17:22 and when I call (Guice/createInjector mm)

17:22 it spits out the exception

17:23 http://google-guice.googlecode.com/svn/trunk/javadoc/com/google/inject/AbstractModule.html

17:23 how can I find out what is wrong exactly?

17:24 how do I find out what Clojure can call upon a class?

17:24 any helpful reflection methods to use?

17:25 amalloy: jlaskowski: createInjector takes an array of Modules, not a single module

17:25 java's Foo.bar(Whatever...) is sugar for arrays

17:25 jlaskowski: right

17:26 but have a look at the full stack trace

17:26 user=> (.printStackTrace *e)

17:26 java.lang.IllegalArgumentException: No matching method found: createInjector

17:26 at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:77)

17:26 at clojure.lang.Reflector.invokeStaticMethod(Reflector.java:202)

17:26 at user$eval17.invoke(NO_SOURCE_FILE:4)

17:26 at clojure.lang.Compiler.eval(Compiler.java:6201)

17:26 at clojure.lang.Compiler.eval(Compiler.java:6168)

17:26 at clojure.core$eval.invoke(core.clj:2680)

17:26 at clojure.main$repl$read_eval_print__5619.invoke(main.clj:179)

17:26 at clojure.main$repl$fn__5624.invoke(main.clj:200)

17:26 at clojure.main$repl.doInvoke(main.clj:200)

17:26 at clojure.lang.RestFn.invoke(RestFn.java:422)

17:26 at clojure.main$repl_opt.invoke(main.clj:266)

17:26 at clojure.main$main.doInvoke(main.clj:361)

17:26 amalloy: augh do not do that

17:26 http://gist.github.com

17:26 jlaskowski: amalloy: ok, will use it

17:27 amalloy: anyway, yes. it can't find a method with that name whose parameters are (Foo), only one whose parameters are (Foo[])

17:28 jlaskowski: you're right!

17:28 lancepantz: does anyone have any experience with the :exposes-methods option to genclass? I'm trying to hook into the servlet init method: https://gist.github.com/756639

17:28 jlaskowski: so how can I call a method that accepts an array?

17:28 amalloy: you can find this out for yourself with clojure.contrib.repl-utils/show

17:28 jlaskowski: ##(doc into-array) is one way; in this case it looks like Guice will also accept an Iterable, so you can just pass it a clojure vector

17:28 sexpbot: ⟹ "([aseq] [type aseq]); Returns an array with components set to the values in aseq. The array's component type is type if provided, or the type of the first value in aseq if present, or Object. All values in aseq must be compatible with the component type. Class objec... http://gist.github.com/756642

17:28 Luyt_: The topic could say 'Don't paste into the channel, use a pastebin like http://paste.pocoo.org/'

17:29 jlaskowski: Luyt_: nice of you :)

17:29 Luyt_: well, #python has it, and many other channels too.

17:30 jlaskowski: HURRAYY - you saved my day, amalloy

17:30 it works fine now

17:30 Luyt_: Freenode's channels are a great resource, because of all the friendly and knowledgeable people on it!

17:30 jlaskowski: it's awesome how quickly it's sorted out!

17:31 Luyt_: ...and some communities are really great.

17:31 lancepantz: we just have a great community :)

17:31 jlaskowski: it's not the first time I just enter the channel

17:31 and get an answer in secs

17:31 unbelievable

17:32 thanks again

17:32 Luyt_: as long as you don't become a Help Vampire (http://slash7.com/2006/12/22/vampires/) it's allright ;-)

17:33 and you can always give back to the community, of course. Like lurking and answering questions from noobs, which are too tedious for the advanced clojurists in here. (Same works in #python)

17:36 amalloy: Luyt_: thanks for the Help Vampire link. it's cute

17:39 Luyt_: amalloy: Cute, yes, but there's also a very warning in there...

17:39 very real*

17:39 amalloy: Luyt_: yes, i'm familiar with the problem

17:40 Luyt_: Now, luckily I haven't seen it happening here yet, since clojure is quite esoteric and only intelligent (?) people are attracted to it, but it happened at #php if I remember correctly.

17:41 ...and also on the python mailing list, at least a few housework-assignment like questions (formulated as demands) come passing by every week.

17:46 TakeV: If I define an atom in one namespace, and have functions that manipulate it in the same namespace, then why is the atom not changing when I call those functions in another namespace?

17:47 pdk: what would be an equivalent to letfn that supports mutual recursion

17:48 dnolen: pdk: you can use trampoline /w your letfns

17:48 pdk: whew boy

17:48 (doc trampoline)

17:48 clojurebot: "([f] [f & args]); trampoline can be used to convert algorithms requiring mutual recursion without stack consumption. Calls f with supplied args, if any. If f returns a fn, calls that fn with no arguments, and continues to repeat, until the return value is not a fn, then returns that non-fn value. Note that if you want to return a fn as a final value, you must wrap it in some data structure and unpack it after trampoline r

17:49 amalloy: TakeV: it should work. maybe post a simple gist that demonstrates your problem?

17:49 qbg: The bindings in letfn are recursive, so there should be no problem

17:50 TakeV: amalloy: A what?

17:50 amalloy: TakeV: http://gist.github.com

17:53 TakeV: Ah, nevermind. It seems that I was calling the wrong atom. Oops.

17:53 rata_: hi

18:04 qbg: I love the foo example that I just added to the readme at https://github.com/qbg/syntax-rules

18:08 rata_: qbg: nice work =)

18:09 dnolen: qbg: when you got time. you should make a simple github tutorial page comparing common use of CL style macros w/ steps to convert to syntax-rules. The Ring tutorial are a great example IMO, http://mmcgrana.github.com/2010/03/clojure-web-development-ring.html

18:09 qbg: I just need to write some code to define syntax classes, and define a bunch of them now

18:10 (and add syntax-case support also, but that should be rather trivial)

18:10 The power of this library is far beyond syntax-rules at this point

18:11 I need to come up with a better name (and one that isn't too cheesy)

18:28 benreesman: hi quick question: is there some literature that explains the clojure philosophy around when to use types/records/protocols and the multimethod/hierarchy system? what's the idiomatic way of creating types that e.g. know how to print themselves?

18:29 qbg: From what I've seen, you provide an implementation of the print-method multimethod

18:29 (or whatever it is called)

18:29 In addition to toString

18:30 benreesman: specified on the name of the defrecord?

18:30 qbg: You shouldn't need to do any of that for defrecord, only deftype

18:30 If you think you do, you are probably doing it wrong

18:31 What are you trying to implement?

18:32 benreesman: i need a servlet that takes a streaming http endpoint and splits it into multiple streams. i'm just trying to get my head around the new clojure abstractions as i haven't used the language in over a year

18:32 qbg: You use records as a typed map for the protocol system, and types for implementing data structures

18:33 benreesman: types/protocols and multimethods seem to have some overlap in their purpose

18:33 to the untrained eye, that is

18:33 i think i understand the difference between a type and a record

18:33 qbg: Use multimethods if you need hierarchies or multiple dispatch

18:34 Use the protocol system if you need polymorphism on groups of functions

18:34 Use functions if you don't need any of that

18:34 benreesman: is it idiomatic to use multiple dispatch with types/records?

18:34 qbg: types/records only provide single dispatch

18:35 benreesman: so if i want multiple dispatch i should continue to use defstruct?

18:35 qbg: *well, the protocol system

18:35 benreesman: really appreciate your time by the way

18:36 qbg: If you don't need to use the protocol system, you could use just maps instead

18:37 rata_: qbg: what about records vs maps performance?

18:38 qbg: records have potential performance advantages

18:38 dnolen: benreesman: multimethods are more general. I've come to the conclusion they are most useful for the "scripting" layer of an application, where you need the most generality and/or where performance is mostly a wash (triggering IO related things).

18:38 when you know you're interested in performance (some essential data structure) reach for protocols deftype/record

18:39 benreesman: right, i'm not bothered about performance at the moment, i just want to use the most idiomatic type and dispatch abstraction. i like multiple dispatch better in general but was always bothered by the lack of a canonical type field for the types. i was wondering if defrecord solved that.

18:40 qbg: defrecord/deftypes creates classes, so they have a type

18:42 benreesman: maybe what i need to do is read some code? any pointers to a non-trivial open source project written in a modern and idiomatic clojure style?

18:43 dnolen: qbg: about syntax-rules. +& is a bit weird, considering what it does - it's a grouping operator. also +sym's are kinda ugly. why not just use keywords? and let the user specify which keywords they want to allow as part of the macro.

18:43 qbg: For full-blown stuff, there is the gvec stuff in core

18:43 benreesman: wonderful i'll have a look

18:43 qbg: dnolan: +& is technically redundant at this point (+head and ...)

18:44 benreesman: much obliged

18:46 dnolen: qbg: sure, mostly critique about +sym convention. why not keywords?

18:48 joshua__: How do I save a file using duck streams to a folder other than the working directory?

18:51 amalloy: did someone improve clojure-mode's eldoc or something recently? i've just noticed that when point is over a var, the minibuffer echoes the current value of that var

18:53 mrBliss: The slides in the recently released Conj video about zippers are ahead of the speaker vid by 20s, which makes it very hard to follow, certainly when he's working in the REPL. (Too bad XBMC only allows an audio offset of maximum 10s). How come the uploaders didn't notice this?

18:56 lazy1: joshua__: Something like https://gist.github.com/756712 ?

19:05 qbg: Sorry, got disconnected

19:05 dnolan: I used +syms because they are commonly used in source code

19:05 And so they are unambiguous

19:06 Also, because syntax-parse has ~syms for additional directives

19:07 joshua__: lazy1: thanks.

19:08 lazy1: I got confused because I tried \\temp\\blah instead /temp/blah

19:08 lazyl: and that faile

19:12 lazy1: joshua__: To be OS agnostic, you probably want to join part on File/separator

19:14 Though Java might do the / to \ conversion for you, I don't know

19:17 amalloy: lazy1, joshua__: i think it does the conversion *sometimes*, as if that were helpful

19:19 Guest10433: http://pastebin.com/z5P2n9vM is one of these preferable to the other in clojure?

19:20 lancepantz: Guest10433: i like a better

19:21 Guest10433: lancepantz: thanks. i was just wondering if one way was considered better style

19:21 amalloy: Guest10433: a for sure. the (thingN)s should all line up; i prefer a, but if you indented lines 9 and 10 to match line 8 i think that would be acceptable

19:22 Guest10433: thanks amalloy.

19:24 joshua__: Hmm. How do I create a folder that doesn't exist?

19:25 lazy1: joshua__: Most of FS functionality is in java.io.File (see http://download.oracle.com/javase/6/docs/api/java/io/File.html)

19:25 amalloy: $google java io file create

19:25 sexpbot: First out of 127000 results is: Creating a File | Example Depot

19:25 http://www.exampledepot.com/egs/java.io/createfile.html

19:26 amalloy: hm. not what i was hoping google would turn up, but quite useful anyway

19:28 joshua__: duck-streams in contrib turns out to have a make-parents command. I just need to create a file that has a path there.

19:31 So something like (duck/make-parents (java.io.File. "path/to/file.txt")) would work =)

19:31 amalloy, thanks that led me in the right direction.

19:35 Yep worked like a charm. Thank you everyone!

19:42 How would I got about declaring a dependency to one of my own projects with lein?

19:43 Like :dependency [[my-other-lein-project "1.0.0-SNAPSHOT"]]

19:43 tomoj: look in your project's project.clj to determine

19:43 amalloy: joshua__: i'm not sure about lein, but in cake you can $ cake install in my-other-lein-project to deploy it to your local repo

19:44 lazy1: lein has install as well

19:44 ninjudd: amalloy: 'lein install' works too

19:44 tomoj: if you are hacking on both projects at once, symlink checkouts/my-other-project to the root of my-other-project

19:44 joshua__: lein install sounds like the right route than =)

19:44 tomoj: and also include the dep

19:45 then when your symlink is in place, the code there will take precedence over a jar in your local repo

19:46 joshua__: This seems to have been surprisingly easy.

19:46 lein install.. 2 seconds later.. lein deps in other project

19:46 no errors ?

19:46 =) very nice

20:27 bendlas: hey

20:28 Can somebody tell me what's going on here

20:28 ,(deftype Vec2 [^double x

20:28 ^double y]

20:28 Object

20:28 (equals [this other]

20:28 clojurebot: EOF while reading

20:29 bendlas: (println :other-type (type other) \newline

20:29 :this-type Vec2 \newline

20:29 :instance? (instance? Vec2 other)\newline

20:29 :=type? (= (type other) Vec2))

20:29 (and (instance? Vec2 other)

20:29 technomancy: bendlas: step one: pastebin

20:29 bendlas: (== (.x this) (.x other))

20:29 (== (.y this) (.y other)))))

20:29 right

20:31 http://pastebin.com/AgNVKFhW

20:31 anyway, when i do (= (Vec2. 5 6) (Vec2. 5 6))

20:32 (instance? Vec2 other) in the overridden equals gives false

20:32 while (= (type other) Vec2) gives true

20:32 wtf?

21:13 qbg: Finally done with implementation of syntax class definition for https://github.com/qbg/syntax-rules

21:13 Now to document and do a commit

21:18 joshua__: Is there a simple way to pass a string to enlive as an html resource?

21:19 Instead of a file/url that is.

21:23 I guess I'll just wip out a regular expression.. seems like it will be faster

21:26 bendlas: joshua__: html-snippet, I think

21:27 * joshua__ watches slime crash.

21:28 joshua__: Didn't work ;p

21:28 ouch

21:30 Apparently that is how its suppose to be done though.

21:31 I think it was just my string being malformed.

21:31 Thanks bendlas!

21:33 bendlas: np

21:41 joshua__: $findfn ["\n\ntest"] "test"

21:41 sexpbot: []

21:41 joshua__: $findfn "\n\ntest" "test"

21:41 sexpbot: [clojure.string/trim clojure.string/triml clojure.contrib.string/trim clojure.contrib.string/ltrim]

21:41 joshua__: omg omg

21:41 The function.. it works =)

21:48 tomoj: technomancy: thanks! I went to check sample.project.clj for the syntax for exclusions, and found exactly the log4q exclusions I needed :D

21:48 er, log4j

22:00 dnolen: so for contrib 1.3.0 how do I include a contrib library in a project.clj?

22:10 qbg: Finally, syntax class definitions

22:10 And an improved plet example

22:11 Awesome error messages FTW

22:13 Needs syntax sugar for pattern variables with a parameterless syntax classes though

22:13 *class

22:30 Berengal: Is it possible to connect a repl to a running clojure process somehow?

22:34 tomoj: there is at least one way

22:34 Berengal: How?

22:34 clojurebot: with style and grace

22:34 tomoj: emacs user? if not, there may be a way, but I don't know it

22:34 Berengal: Yeah, I'm an emacs user

22:34 tomoj: do you use leiningen?

22:35 Berengal: Both that and maven

22:36 tomoj: you know about `lein swank` and `mvn clojure:swank` (or whatever the maven goal is..)

22:36 Berengal: But maven is probably more relevant to the projects I want to do this with

22:36 Yeah, I do

22:36 tomoj: there is a bit of clojure code you can use to kick off the swank server from your clojure code

22:36 Berengal: Ah, nifty

22:37 tomoj: (swank.swank/start-repl)

22:37 can pass port and host I think

22:38 [port & opts]

22:40 Berengal: That way I can start poking around my objects and whatnot while it's live. Why doesn't every language let you do that?

22:45 wooby: Berengal, https://github.com/relevance/mycroft is a web-based jvm explorer that may also interest you

22:47 Berengal: wooby: So that's kind of a browser-based repl, right?

22:48 wooby: of sorts

22:48 Berengal: Neat

22:49 technomancy: Berengal: the only reason I can imagine other languages lack a repl is that their designers have never used a language with one... but I know that's not true.

22:50 Berengal: technomancy: It's not the lack of a repl as much as the lack of a disecting a running program I'm lamenting

23:03 amalloy: technomancy: it's kinda hard to imagine what a java repl would look like, with everything having to live in classes and methods

23:04 gregh: public static void main>

23:04 amalloy: gregh: and imports? or using the repl to write more than one function?

23:05 gregh: yeah, it's not really practical. But it could be useful in a limited sense

23:05 qbg: My mashup is now a syntax-rules/syntax-case/syntax-parse mashup.

23:07 gregh: related: http://stackoverflow.com/questions/2636044/java-repl-shell

23:07 wide variety of alternatives here: http://stackoverflow.com/questions/397488/is-there-something-like-pythons-interactive-repl-mode-but-for-java

23:43 hippiehunter: when consuming java types am i supposed to access public fields using (.someField instance set-value) ?

23:43 or is that just for methods

23:43 Gigaroby: i think there was somethink like (set!

23:44 (set! (. instance-expr instanceFieldName-symbol) expr)

23:44 all here : http://clojure.org/java_interop

23:46 hippiehunter: thanks

23:48 wooby: i knew lots of people who pre-clojure used groovy or beanshell for a repl

23:50 hippiehunter: is there a way to make set! play nice with doto?

23:54 amalloy: hippiehunter: i don't use set! for interop; can you show me what a set! form for that looks like?

23:54 hippiehunter: (set! (. instance field) value)

23:55 is there something i can use instead of set!?

23:55 or are you just lucky enough not to deal with public fields

23:55 amalloy: the latter, i'm afraid

23:56 Gigaroby: guys I need somethink to remove a element from a seq in a determinate position

23:56 example : (remove 2 '(1 2 3 4))

23:56 =>(1 2 4)

23:58 amalloy: hippiehunter: (doto instance (-> (. field) (set! 10))) maybe?

23:58 joshua__: $findfn 2 [1 2 3 4] [1 2 4]

23:58 amalloy: ,(macroexpand '(doto instance (-> (. field) (set! 10))))

23:58 sexpbot: []

23:58 clojurebot: (let* [G__870 instance] (-> G__870 (. field) (set! 10)) G__870)

23:58 joshua__: $findfn 2 [1 2 3 4] `(1 2 4)

23:58 sexpbot: []

23:58 joshua__: $findfn [1 2 3 4] 2 `(1 2 4)

23:58 sexpbot: []

23:59 amalloy: joshua__, Gigaroby: no single function does it; you have to chain one or two together

23:59 hippiehunter: -> is one of those things Ive not gotten around to understanding, might you point me in the direction of a noob friendly explaination

Logging service provided by n01se.net