#clojure log - Jan 08 2011

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

0:28 joshua__: What web hosts do you like for Clojure w/ MongoDB as the database?

0:31 tomoj: the same ones I like for anything else

0:31 if you find a host that supports clojure w/ mongo without supporting everything else, let me know

0:33 amalloy: i'm sure there's an easy way to do this, but i'm not sure what it is: how do i test whether something is specifically (), the empty list, and not eg [] or {}?

0:34 i don't need to worry about lazy seqs here because this is an unevaluated macro parameter

0:37 qbg: ,(= () ())

0:37 clojurebot: true

0:37 qbg: ,(= () [])

0:37 clojurebot: true

0:38 qbg: Hmm

0:38 amalloy: &(identical? () ())

0:38 sexpbot: ⟹ true

0:38 qbg: identical? is almost certainly the wrong thing

0:38 amalloy: qbg: agreed

0:38 qbg: Explicit type check?

0:39 (and (= () ()) (list? ()))

0:39 ,(and (= () ()) (list? ()))

0:39 clojurebot: true

0:39 amalloy: qbg: yeah, i think i'll have to do something like that. thanks

0:39 qbg: seq? would probably be better

0:40 I think lazy seqs might be able to get into your code

0:40 amalloy: qbg: yeah, i'm actually using seq? already for something else; i'm just going to reorder the checks so that i do seq? first

0:41 although i'd be interested in how a lazy-seq could sneak in

0:41 qbg: Macro produces lazy seq which is passed to your macro

0:41 I think that has happened to me before and it bit me

0:41 amalloy: qbg: my macro expands first

0:41 qbg: What if another macro expands into a usage of your macro?

0:42 amalloy: *squint* maybe you're right...that makes my head hurt

0:42 yeah, i think so. jeez, good catch

0:43 tomoj: the fact that I have no idea what problem you're talking about scares me

0:43 qbg: ,(list? (lazy-seq nil))

0:43 clojurebot: false

0:44 qbg: ,(list? (lazy-seq ()))

0:44 clojurebot: false

0:44 qbg: The use of syntax-quote is a big cause of the problem

0:44 amalloy: &(macroexpand '(-> x ()))

0:44 sexpbot: ⟹ (nil x)

0:44 qbg: ,'`(foo ~1 ~2)

0:44 clojurebot: (clojure.core/seq (clojure.core/concat (clojure.core/list (quote sandbox/foo)) (clojure.core/list 1) (clojure.core/list 2)))

0:44 amalloy: fwiw, this is the amusing problem i'm fixing

0:45 tomoj: so the problem is that sometimes you wish you had () when you actually have an empty lazyseq?

0:46 qbg: Sometimes things that look like lists aren't list?

0:48 tomoj: so the real problem is finding things that look like (), not finding ()?

0:50 except that [] looks awfully like ()..

0:52 amalloy: tomoj: tbh i don't think it matters much how i treat [] and {}, but i'm choosing to duplicate the existing functionality just in case someone is depending on it

1:01 tomoj: the existing functionality picks out ()?

1:03 amalloy: tomoj: i'm looking at rewriting ->

1:03 &(macroexpand '(-> foo ()))

1:03 sexpbot: ⟹ (nil foo)

1:03 amalloy: that's known to be ridiculous code, and (foo) might occasionally be useful

1:04 so i want to pick out (), but preserve existing behavior: ##(macroexpand '(-> foo [])) ##(macroexpand '(-> foo {}))

1:04 sexpbot: (macroexpand (quote (-> foo []))) ⟹ ([] foo)

1:04 (macroexpand (quote (-> foo {}))) ⟹ ({} foo)

1:07 tomoj: wow that is one long character

1:08 amalloy: tomoj: sexpbot's arrow?

1:08 tomoj: yeah

1:48 cheezey: how can i reference a jar library in clojure? o_o

1:49 specifically, just importing some class

1:49 amalloy: cheezey: how are you starting your repl? you need to make sure the jar is on your classpath, and how to do that depends

1:50 cheezey: amalloy: im pretty sure the jar is in my class path when i start the repl

1:50 amalloy: cheezey: okay. then you just (import com.mydomain.MyClass)

1:51 or (import (com.mydomain Class1 Class2)) if you have lots in the same package

1:52 cheezey: amalloy: oh thanks. i forgot to reset my global variable :x

1:52 amalloy: *chuckle*

1:53 cheezey: amalloy: thnx got it working :D

4:29 bartj: I am just starting out with Clojure web dev

4:29 and would like to know which I should start out with:

4:29 enlive+moustache or compojure

5:16 mids: bartj: there is also #clojure-web if you are interested

5:16 bartj: are you familiar with any web framework in other languages?

5:17 bartj: mids, I haven't used any framework till date. :)

5:18 mids, I have just written a compojure small app in the time I posted the question here

5:18 and you answering it, so my guess is that it is great :)

5:18 mids: yeah compojure seems to be getting the most traction

5:19 but all of them are very leight weight

5:19 plus you could swap out hiccup for enlive easly

5:19 I am trying to find a nice diagram showing the clojure web ecosystem.. but not much luck yet :(

5:20 found it! http://www.glenstampoultzis.net/blog/clojure-web-infrastructure/

5:21 clgv: hello, is there any core or contrib macro doing the following: check if an expression is not null and in this case applying a given function on it or else returning nil?

5:23 if not, I guess I need to write it - but I dont want to reinvent the wheel every time ;)

5:25 mids: (when-not (nil? exp) (f exp))

5:25 I am not aware of anything shorter

5:25 clgv: thats correct, but it needs the expr written twice ;)

5:26 (apply-when nil? expr f) or something like this would be nice. but I guess it's not written yet ;)

5:26 or better apply-when-not ;)

5:27 mids: just go ahead and make a function or macro for that :)

5:27 bartj: mids, much thanks

5:28 clgv: I'll do. just wanted to check if anyone knew an existing one.

5:59 raek: clgv: (and expr (f expr))

6:00 clgv: 'fnil' is worth checking out too

6:01 clgv: I defined this now: (defmacro apply-not-nil [func expr] `(let [expr-result# ~expr] (when expr-result# (~func expr-result#) ) ) )

6:01 raek: ,(macroexpand-1 '(and expr (f expr)))

6:01 clojurebot: (clojure.core/let [and__3468__auto__ expr] (if and__3468__auto__ (clojure.core/and (f expr)) and__3468__auto__))

6:02 raek: ,(macroexpand '(and expr (f expr)))

6:02 clojurebot: (let* [and__3468__auto__ expr] (if and__3468__auto__ (clojure.core/and (f expr)) and__3468__auto__))

6:02 mduerksen: clgv: that's not exactly correct, since expr could become false. in that, func wouldn't be invoked as well

6:03 clgv: ok then I have to use nil? - just got use to simply use when from reading clojure source ;)

6:03 raek: clgv: there's also -?> in contrib. it works like ->, but returns nil as soon as some function in the chain return nil

6:03 clgv: raek: that might be what I was looking for

6:03 mduerksen: raek: didn't know of that one, nice

6:04 raek: ,-?>

6:04 clojurebot: java.lang.Exception: Unable to resolve symbol: -?> in this context

6:04 raek: ,(use '[clojure.contrib.core :only (-?>)])

6:04 clojurebot: java.io.FileNotFoundException: Could not locate clojure/contrib/core__init.class or clojure/contrib/core.clj on classpath:

6:04 clgv: ,(use 'clojure.contrib.core) (doc -?>)

6:04 clojurebot: java.io.FileNotFoundException: Could not locate clojure/contrib/core__init.class or clojure/contrib/core.clj on classpath:

6:05 raek: &(use '[clojure.contrib.core :only (-?>)])

6:05 sexpbot: ⟹ nil

6:06 raek: &(let [f (constantly false), a (constantly :a)] (-?> :foo f a))

6:06 sexpbot: ⟹ :a

6:06 raek: &(let [f (constantly nil), a (constantly :a)] (-?> :foo f a))

6:06 sexpbot: ⟹ nil

6:07 raek: ok. -?> checks for nil rather than falseness

6:07 clgv: it's what the api documentation says too ;)

6:08 but it's exactly what I was looking for. I thought that might be a common use case that is already implemented in contrib ;)

6:11 fliebel: raek: What would you do if you want to drop out with false? Sortof reverse fnil ;)

6:13 raek: false but not nil?

6:13 that feels a bit unusual

6:16 I guess I'd put together something like and, fnil or -?>, but with 'false?' as the predicate

6:18 clgv: I just played a bit with macros and learned how to get to the function that was passed as a parameter.

6:18 if I call the macro with (test-macro func-name) it is a symbol within the macro which I have to "resolve" to get a "var" which I can pass to "var-get" to get the function.

6:18 is that the usual way or is there a shortcut?

6:19 thats what I did with: (-?> func resolve var-get)

6:19 and checked if it really is a function with fn?

6:21 raek: it's not certain that you can get the function of the argument, since that's a run-time value and macros are applied at compile-time

6:21 are you sure you need a macro in this case?

6:22 macros receive _code_ and return new code

6:23 (if the symbol happens to refer to a var (global variable), then you can actually look at the var the way you did, but this does not work if the user passes a symbol introduced by let or fn)

6:24 bortreb: is there any way to get a file object representing the jar file in which a java class resides?

6:24 raek: you can do a lot of magic with higher order fucntions

6:24 clgv: it's going to return code but therefor I want to pass a function (for brevity) that is used within the macro

6:25 I could also put that functions code directly into the macro at that position

6:25 but I think that would look really complicated

6:25 raek: you can put it in a separate defn

6:26 clgv: yes, that is what I plan to do

6:26 raek: just use it outside any syntax-quote blocks

6:27 you could split the functionality into two parts:

6:27 clgv: define function: (defn funcname [...] ...)

6:27 call macro: (testmacro funcname ...)

6:27 raek: one function that does the job, and one macro that uses that function and passes another function as an argument

6:28 clgv: hm ok. that is another possibility.

6:28 raek: (defmacro testmacro-f1 [x] (testmacro-core f1 x))

6:28 (defn testmacro-core [f x] ...)

6:29 bortreb: figured it out

6:29 raek: (defn f1 [...] ...)

6:29 bortreb: you use getProtectionDomain and go from there

6:29 clgv: oh, you meant the same idea. thats exactly the layout.

6:29 since the testmacro-cor in my case can't now f1

6:30 but testmacro-f1 knows it

6:31 raek: macros are a bit contageous and hard to compose (cannot be applied). best to do as little as possible in them

6:31 http://vrac.cgrand.net/DSL.pdf

6:33 clgv: thats true, but I am doing some generic function definition interception that shall be transparent

6:33 I did it for two purposes in a copy, paste & adjust manner and now want to generalize it to a core that is used for both purposes to avoid the copy&paste

6:36 raek: are these your slides on the DSL topic?

6:36 raek: no, not mine

6:37 they are from Cristophe Grand's talk at the Conj

6:38 clgv: ah ok. thats what the bottom line says. but I didn't know if "he might be you" ;)

6:43 is there any place (news page) where progress on development on clojure 1.3 is reported in more detail? so that one gets a feeling when it might be finished as stable release?

7:12 Leonidas: What is the best way to iterate over a dict like {"Leonidas" #{#"Leonidas\S*"}} and terminate on the first item that matches a predicate and returning its key?

7:12 reduce does a bit too much

7:14 raek: Leonidas: that looks like a job for 'some'

7:14 it steps through a colleciton and runs a function on each element

7:14 if the function returns non-nil, it stops and returns that

7:15 if the function returns nil, it continues with the next thing

7:15 clgv: (first (filter pred map)) would work to I guess - this way the predicate does not have to return the entry

7:16 and shouldnt be much overhead either due to lazy

7:17 Leonidas: oh, filter is a good idea

7:17 raek: I'm already using some

7:17 (some #(re-matches % nick) the-set)

7:17 raek: ,(let [s "Leonidas ", f (fn [[key re]] (when (re-find re s) key))] (some f {"found!" #"Leonidas\S*"}))

7:17 clojurebot: "found!"

7:17 raek: ok

7:18 Leonidas: hmm? some returns a value?

7:18 raek: yes

7:18 Leonidas: in my repl, I get true and false

7:18 raek: it returns the value of the function

7:19 which does not have to be a predicate

7:19 Leonidas: oh, I see. odd? returns true and false, apparently :)

7:22 raek: ,(let [s "Leonidas ", f1 (fn [s res] (some #(re-find % s) res)), f2 (fn [[key res]] (when (f1 s res) key))] (some f2 {"found leonidas" #{#"Leonidas\S*"}}))

7:22 clojurebot: "found leonidas"

7:24 Leonidas: raek: that looks good. my tries with filter weren't as successful

7:25 raek: some and first+filter should both be able to solve the problem, I think

7:26 clgv: I guess you should prefer filter if you want to have exactly whats in the map. otherwise you have to make the function you pass to some returning it's parameter at the end

7:26 Leonidas: yeah, I suppose. i just got tangled up in nested functions.

7:26 clgv: otherwise if you even want to alter the found data, some should be better

7:28 * Leonidas tries it for himself; will post the code for dissection in a moment, thank you both :)

7:38 Leonidas: http://paste.pocoo.org/show/317060/ <- I suppose at this point I should have used for?

7:39 clgv: you could definitely skip the map

7:40 (just-nicks (first (filter criterion mapping)))))

7:40 and I guess "just-nicks" is superfluous too

7:41 it can be replaced by "first" or if it is a map entry by "key"

7:43 it looks a bit odd using some within a predicate of filter - but it might totaly make sense depending on your taks and data structure - I cant tell without knowing both ;)

7:46 Leonidas: clgv: ok, you're right. as I just want the first element's key, there's no need for the complete map

8:05 fliebel: Is there a way I can typehint like #{interface1 interface2}, without specifying a specific class?

8:11 AWizzArd: Clojures type hints allow you to work on the first level, that is: the set. This you can type hint.

8:12 But type hinting that it contains instances of a specific interface is not possible.

8:12 However, the functions that work with the elements from this set can type-hint them, in doseq or map for example.

8:14 fliebel: Right. Well, since it's not for Java interop, I guess I can also do (assert (clojure.set/subset? (ancestors class) #{interfaces}))

8:15 But actually I don't need t at all. I'm just trying to understand generic programming.

8:19 But so far it seems generics are mainly a static typed feature. And besides that, iSeq is pretty generic and versatile.

8:22 AWizzArd: You know anything about that? ^

8:23 AWizzArd: Generics are a tool for static typing.

8:24 They are not required in dynamically type languages.

8:25 fliebel: AWizzArd: I met a Haskell guy yesterday, who had a generic function that created a GUI based on a data structure.

8:26 AWizzArd: Yes, you can build a parser for Clojure too that takes an Object and constructs a GUI out of it.

8:26 In fact, I am implementing something similar in Clojure.

8:27 This is comparable to html + a web browser.

8:27 The browser receives an object, a (html) String here, and constructs an UI.

8:27 In Clojure you can send your client a spec, which then constructs a (swing) UI.

8:28 clgv: AWizzArd: I just read your comment - what exactly are you implementing?

8:29 fliebel: AWizzArd: But is this like a DSL, or more like a visualization? In other words, do I need to specify what I want, or do I just pass it mydata, and have it figure out a layout and the right controls?

8:31 AWizzArd: clgv: my company needs several UIs. I will implement an empty Swing window soon, with some loading functions. This App will have a http client and request UI specs from a server. The server will send specs, corresponding to the authentication level of the requesting user of the app. Then the client paints its gui.

8:32 This way the users can have an updated UI and don't really need much implementatiotn.

8:32 clgv: AWizzArd: ah ok. interesting idea :)

8:32 AWizzArd: fliebel: in fact, I just finished developing a helper DSL for swing applications. I am in the process of writing the documentation, before I will publish it in the coming days.

8:33 clgv: this way my Swing client is basically similar to a browser that receives html + js.

8:33 My program will download Strings that it an read and eval.

8:34 The client will require access to the network. For my use cases this is fine.

8:34 clgv: saves you from repeated update installations for the client applications...

8:34 AWizzArd: Yes. Also I don't need to write html and js, but write Clojure instead :)

8:35 clgv: thats a big pro - avoiding html+js ;)

8:35 AWizzArd: Enables me to provide any user with the empty stub, which is basically my "Firefox". Inside it any application can be downloaded.

8:36 fliebel: AWizzArd: What I was thinking of, and what the Haskell guy had, was more like XSLT. You just send it data, and it transforms it to Swing. So I imagine that every seq becomes a fieldset/JPane, with controlls on it suitable for the type of node.

8:36 clgv: you could also describe it with the term "thinclient" or something like that ;)

8:37 fliebel: Meh, I like the browser metaphor better.

8:37 AWizzArd: fliebel: in some days I can give you a link and you can check out if my lib is similar in some way to what you want.

8:37 fliebel: AWizzArd: Cool :)

8:37 AWizzArd: I basically need to add more doc strings and write up some examples.

8:38 fliebel: okay

8:39 AWizzArd: But then you can construct several UIs. That is: containers that contain ui components. Those UIs can then be seen as new ui components themselves that you can reach around and put anywhere you want them to be. That allows for easy reusability.

8:40 Chousuke: I once read about a pretty cool Haskell UI library. It seemed perfectly composable.

8:42 I don't remember the exact details of how it worked but you could write a UI for pong that is controlled by the user, then write a generic "mirror" UI transformer, combine the pong UI with the transformer and get two synchronised views, one normal, the other mirrored :P

8:42 it was pretty cool

8:43 AWizzArd: In principle I could do this too. If the function that provides the UI with data has subscribers, then I can simply instantiate another one of my UIs and have it subscribed.

8:43 It could also be a slightly or massively modificated UI.

8:44 This would also work over the network, so that those "mirrors" are not on the same computer.

8:45 Chousuke: hmm, but then keeping the UIs synchronised will be a problem

8:45 don't try to do too much :)

8:46 AWizzArd: I won't try too much. What I implemented is a very simple tool that will reduce my LOC, provide better readability, require less scrolling, are easier to maintain and very reusable.

8:47 It's a small lib. But it also brings data binding to swing, which is also nice.

8:50 no_mind: [OT] can I make my living by writing clojure code ?

8:50 clgv: does anyone know how to do syntax quoting in a nested way?

8:50 AWizzArd: no_mind: I do :)

8:50 no_mind: lucky you... where do I find remote clojure jobs ?

8:51 clgv: I have two nested syntax quotes and in the inner one I want to unquote a symbol thats defined outside

8:51 ~~symb does not work

8:51 AWizzArd: clgv: best would be if you could provide a minimal example.

8:51 clojurebot: http://clojure.org/data_structures#toc10

8:56 clgv: hmm I guess I should not nest syntax quotes

8:57 fliebel: clgv: I think there might be a function counterpart of !, like unquote or whatever.

8:57 *~

8:58 clgv: unquote it is

8:58 hmm perhaps I have to use that one

9:09 MrHus: Given the following code:

9:09 (defrecord Monster [x y]

9:09 GameElement

9:09 (paint [this g] (paint-rect g this Color/RED)))

9:09 (defn add-element

9:09 [type x y]

9:09 (dosync

9:09 (alter game-elements conj (type x y))))

9:09 Sorry

9:09 ill pastebin instead

9:09 I have the following code: http://pastebin.com/7dDQWk3R.

9:10 Can i do this: (add-element Monster. 10 10)

9:12 fliebel: MrHus: huh? Sure…

9:14 Maybe you'll want to do (new type x y)

9:14 MrHus: fliebel: I'm getting a class not found error when I try.

9:14 fliebel: ill try new

9:14 raek: you cannot do that with normal java constructors, but I don't know about record constructos

9:14 new is a special form, and you cannot "apply" it with a run-time value

9:15 it's easier to call the function like this: (add-element #(Monster. %1 %2) 10 10)

9:16 fliebel: Or why not (add-element (Monster. 10 10))?

9:17 raek: it's often recommended to write a constructor function for records

9:17 fliebel: raek: Why won't new work? Does it need a literal class?

9:17 MrHus: Thanks for the suggestions, I thought it had something to do with my enviorment.

9:17 raek: yes

9:17 it needs the class at compile time

9:20 to summarize: constructors are not first-class values

9:21 pdk: so functions are still 3/5ths of a person

9:23 clgv: java.lang.Exception: Can't create defs outside of current ns - whats that supposed to mean if I stay within the same namespace?

9:23 Chousuke: hm

9:24 what line is generating that exception?

9:24 clgv: hm hard to determine since it's a macro

9:24 Chousuke: if you're doing something like (def foo/bar) that won't work.

9:24 well look at the macro expansion then

9:25 clgv: hm that hint is good. I'll see if it shows something like that

9:25 Chousuke: If it's your own macro, probably there's a mistake in your use of the syntax-quote

9:25 that causes the a `(def foo ...) form to become (def blahnamespace/foo ...)

9:26 though I think that should still work if the namespace is the current one, but I'm not sure.

9:26 clgv: I guess that could be true

9:27 raek: I think you'd want something like `(def ~'foo ...)

9:28 clojure.contrib.def has some macros like that

9:29 clgv: oh that hit a point I didnt understand until now - whats the difference between `(def ~'foo ...) and `(def foo ...)

9:30 raek: all symbols inside a syntax-quote are resolved to a namespace

9:30 MrHus: Can clojure records extend java interfaces?

9:30 raek: ,`(foo)

9:30 clojurebot: (sandbox/foo)

9:30 clgv: ,`(def ~'foo ...)

9:30 clojurebot: DENIED

9:31 clgv: ,`(def ~'foo 5)

9:31 clojurebot: DENIED

9:31 raek: this is to avoid symbol capture

9:31 but in certain cases you really need the symbol as-is

9:31 clgv: ,`(~foo)

9:31 clojurebot: java.lang.Exception: Unable to resolve symbol: foo in this context

9:31 raek: &`(~'foo)

9:31 sexpbot: ⟹ (foo)

9:32 clgv: ah ok

9:32 raek: like in macros expanding into def forms

9:34 clgv: yeah it definitely has to do with the fact that the parameter I provide to a macro is resolved too early

9:34 raek: the ~ means "insert the result of an expression here" and the expression you insert is the symbol (quoted, to give the symbol itself, rather than the value it stands for)

9:36 if you want to insert something passed as an argument to the macro into a syntax-quoted expression, you need to add an unquote for it

9:36 clgv: wow that looks really strange than: ~'~'foo since it's in a nested syntax-quote

9:36 raek: huh?

9:37 &`(a ~'~'foo b)

9:37 sexpbot: ⟹ (clojure.core/a (clojure.core/unquote (quote foo)) clojure.core/b)

9:37 clgv: yeah I knew the basic part - but I didnt know that the symbol already gets resolved at that point

9:37 &`(a `(b ~'~'foo b)

9:37 sexpbot: java.lang.Exception: EOF while reading

9:37 raek: syntax-quote reslove the symbols at _read-time_.

9:37 clgv: &`(a `(b ~'~'foo b))

9:38 sexpbot: ⟹ (clojure.core/a (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/b)) (clojure.core/list (quote foo)) (clojure.core/list (quote clojure.core/b)))))

9:38 clgv: and it doesnt if I quote it with ' - ok

9:38 raek: clgv: what does ~'~'foo even mean?

9:39 you rarely need to use ~' but ~'~' I have never seen

9:39 ~ is only meaningful inside a syntax-quoted expression

9:39 clojurebot: regular expressions is http://www.regular-expressions.info/tutorial.html

9:40 clgv: it is within a nested syntax quote

9:40 with only ~' it still gets resolved

9:40 raek: nested?

9:40 are you writing a macro that writes macros?

9:40 clgv: yes

9:41 raek: i.e. a macro that expands into a defmacro?

9:41 clgv: and it works now :)

9:45 raek: in that case, I guess it makes sense :-)

9:45 clgv: yeah it does. it's kinda meta meta language ;)

9:46 when does clojurebot post this topic links it read keywords of?

9:49 raek: ~ when the line starts with a tile, I think

9:49 clojurebot: trampoline is http://groups.google.com/group/clojure/browse_thread/thread/6257cbc4454bcb85/3addf875319c5c10?#3addf875319c5c10

9:50 raek: clojurebot: thank you. have some botsnack.

9:50 clojurebot: thanks; that was delicious. (nom nom nom)

9:50 clgv: lol

9:50 clojurebot: take a rest. ;)

9:50 clojurebot: rest never returns a unicorn

9:50 clgv: lol

9:51 it has an index of the clojure google group?

9:51 ~ clojure 1.3

9:51 clojurebot: /Projekt/swank-clojure/ is where I keep the cloned git repo

9:51 clgv: ~ macro

9:51 clojurebot: macro are just a game with symbols

9:52 raek: huh... that's my path

9:53 ah

9:53 "~/Projekt/swank-clojure/ is where I keep the cloned git repo"

9:53 ("projekt" is Swedish for "projects")

9:53 hence, the funky spelling

9:54 the bot must have treaded that as an order to add a fact

10:03 clgv: lol. projekt is also german ;)

10:03 you are involved in swank-clojure?

10:04 raek: no. I think that line what from when I tried to explain my emacs setup

10:04 clgv: ah ok

10:07 clojurebot: help

10:07 clojurebot: help is http://clojure.org

10:07 clgv: lol k. I thought he could tell me what he can do ;)

10:08 skelter: clojurebot:

10:08 clojurebot: #<ClassCastException java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;>

10:16 clgv: skelter: you hurt him badly! ;)

10:25 shortlord: is there any built-in clojure method to get the position of the first occurence of an item x in a vector?

10:30 mrBliss: ,(.indexOf [1 2 3] 2)

10:30 clojurebot: 1

10:35 shortlord: mrBliss: thx

11:17 raek: fogus`away: re Marginalia: is it possible to extract the docstrings of protocols?

11:17 rrc7cz: is there any contrib fn for converting a map to a query string like foo=bar&baz=boo, including urlencoding?

11:29 raek: rrc7cz: there's functions in Ring for that: http://clojuredocs.org/ring/

11:29 url-(en|de)code does the encoding part

11:30 rrc7cz: raek: perfect, thank you

11:30 clgv: isnt a protocol just a map? I thought you can simply get the docstrings out of this map

11:30 raek: found this, but it seems to be private: https://github.com/mmcgrana/ring/blob/master/ring-core/src/ring/middleware/params.clj#L17

11:32 rrc7cz: raek: I started just building my own - and I'm not sure it's worth a Ring dep - but I'm sure there's some edge cases Ring has accounted for that mine wouldn't

11:32 raek: it handles multiple occurances of the same key in a, IMHO, complicated way

11:33 foo=bar becomes {"foo" "bar"}, but foo=bar&foo=baz becomes {"foo" ["bar" "baz"]}

11:34 rrc7cz: for now I actually just have to go in the other direction, m->s

11:35 the simple way seems to be something like: (apply str (butlast (interleave (map name (keys m)) (repeat "=") (vals m) (repeat "&"))))

11:36 raek: also, the URL encoding part is in java too: http://download.oracle.com/javase/6/docs/api/java/net/URLEncoder.html#encode(java.lang.String, java.lang.String)

11:49 pevjan: has anybody implemented a CMS in clojure?

11:52 Berengal: Is there a way to undefine a var?

11:54 ns-unmap

11:56 Different question: Is it common to use Java exceptions directly in Clojure, or do you use some other form of non-local return?

11:57 fliebel: pevjan: Not that I know of. LauJensen has a static site generator though. And I and devn where going to write one to, but don't expect that one anytime soon ;)

11:58 Berengal: I don't know, but I was told that try/except is bad as a control structure.

11:58 LauJensen: pevjan: Ive built a CMS in Clojure, though its not released yet its what I use to build clojureql.org with

12:00 cemerick: Berengal: Java exceptions are used when appropriate/necessary, but there are other options: error-kit and condition libs in contrib. A holistic solution looks like it's in the oven as well: http://dev.clojure.org/display/design/Error+Handling

12:00 fliebel: LauJensen: Oooh, will you release it sometime?

12:01 LauJensen: fliebel: Yea I think it would be a shame not to

12:01 cemerick: Berengal: the latter is the result of discussions on clojure-dev (and elsewhere); lately, http://groups.google.com/group/clojure-dev/browse_frm/thread/734ee59f6cbc1b55# and http://groups.google.com/group/clojure-dev/browse_frm/thread/c552e06a0e245d74#

12:02 Berengal: cemerick: Thanks for the links

12:02 fliebel: LauJensen: Is it ClojureQL-dedicated, like the thing you use for bestinclass, or is it a nicely done, modular and reusable.. thing?

12:02 LauJensen: fliebel: Totally reusable, its made for general purpose

12:06 fliebel: LauJensen: Does it have plugins and hooks?

12:35 LauJensen: fliebel: Not yet. Currently it has a texteditor in which you write the content of your page. Then the backend renders a live preview of your page by knitting together your markdown content with an html template, using enlive. Thats the gist of it. Its as easy as Tubmlr to use

12:45 fliebel: LauJensen: Cool :)

13:18 devn: fliebel: :D

13:24 Berengal: So I have a list of names, and I want to define a bunch of functions with a generic implementation based on those names. What's the best way to do this?

13:29 Right now I have a function that makes the defn form, and I do (doseq [foo foo-list] (eval (gen-defn foo))) at the top-level

13:31 raek: Berengal: an alternative could be to use that code in a macro

13:32 (defmacro define-foo-functions [& names] (cons 'do (for [foo names] (gen-defn foo))))

13:34 (define-foo-functions x y z) => (do (defn x ...) (defn y ...) (defn z ...))

13:34 Berengal: raek: And is that better?

13:36 raek: well, for top-level stuff, maybe macros and eval are fairly equivalent...

13:37 Berengal: It just seems a bit gratuitous to be defining a macro only to use it only once right away

13:39 Although it seems this would be general enough to maybe exist already

13:40 raek: a common pattern seems to be to name such macros as def____ and have one call per name

13:40 (deffoo x) (deffoo y) (deffoo z)

13:40 but I'm a bit uncertain what's considered ideomatic in your case

13:41 Berengal: Indeed, but that gets a bit old in some cases

13:41 raek: or whether using eval is something bad in that case

13:42 Berengal: Is there any difference between (defn foo [bar] baz) and (eval '(defn foo [bar] baz)) at the toplevel anyway?

13:47 clgv: a question that came to my mind while reading an article: is there any tool for autoformatting clojure code according to some settings, e.g. suggested "clojure format" and "personal format"?

13:56 LauJensen: clgv: Have you seen marginalia?

13:59 http://jaxenter.com/interview-clojureql-overhaul-33262.html

14:05 clgv: LauJensen: is that a tool for it?

14:05 LauJensen: clgv: marginalia emits an html page which has all of your code on the left and all of your doc strings / examples on the right. Its a pretty auto-doc you might say. Check out fogus' github repo

14:06 raek: clgv: emacs can auto-indent your code, if that was what you were asking about

14:07 clgv: LauJensen: ah ok. I thought more of something like auto-formatting of code like it is done in IDEs e.g. eclipse.

14:07 bobo_: i know netbeans can format clj code. guess eclipse can aswell?

14:09 clgv: I ask mainly because I didn't like the usual lisp formatting and found my own style to be able to read my code fast. but considering sharing or releasing code for others this could be an issue.

14:13 LauJensen: it will be an issue

14:13 (trust me, we've been over this a few times)

14:13 clgv: I read some comments about it.

14:13 bobo_: i dont find it an issue. the reader should be able to autoformat it? unless you are working on something togheter, then it might cause unesecary conflicts and such

14:13 LauJensen: I also comment on this in my blogpost "Taking uncle bob to school"

14:14 clgv: I know - I read that one a few hours ago ;)

14:14 bobo_: although, github is to good at vieweing sourcefiles

14:14 so it might be an issue there =)

14:15 clgv: so nobody ever bothered to write a configurable formatter since it's not an issue if all stick to the formatting guidelines? ;)

14:16 bobo_: you want an extyernal tool?

14:16 external from your editor that is

14:16 clgv: I know that there is none for CCW stable yet - but I dont know what is coming there next. there seems to be a lot in development

14:17 bobo_: oh, i think i tried that yeasterday. i thought it worked? maybe i remember wrong. that happens alot =)

14:18 clgv: I have CCW 0.0.64 right now. is there a new release?

14:18 maybe you tried new unstable builds?

14:21 bobo_: im not sure, dont think my code was much unformated anyway. maybe it can do some simple stuff?

14:25 looks like it can only indent the current line

14:29 bartj: I am not able to see any syntax highlighting in emacs for clojure files

14:29 devn: do you have clojure mode?

14:30 bartj: I have clojure-mode turned on like this in my .emacs:

14:30 (add-hook 'clojure-mode-hook 'turn-on-paredit-mode)

14:35 tomoj: that doesn't look like it should do anything

14:36 when you are looking at a clojure file and see no syntax highlighting, look down near the bottom of emacs, there should be some text between parens. what is it?

14:37 raek: bartj: that ativates paredit when clojure-mode is activated.

14:39 if you install clojure-mode using package.el, I don't think you have to add anything to the .emacs file yourself

14:39 bartj: I guess I am expecting somewhat of vimclojure (rainbow colors!) effect with clojure-mode; which apparently, just isn't the case

14:40 tomoj: rainbows are not built in

14:41 raek: bartj: http://dishevelled.net/elisp/rainbow-parens.el

14:42 bartj: may I ask, which emacs themes are popular for editing clojure files?

14:45 msappler: hey why is this leading to a StackOverFlow : ? - I know that it works if you ` quote it... or is this just bad style?

14:45 <msappler> (defmacro testmacro

14:45 <msappler> ([a b] (+ a b))

14:45 <msappler> ([] (testmacro 1 2)))

14:45 <msappler> =>(testmacro)

14:45 <msappler> java.lang.StackOverflowError

14:46 devn: what is the technical term for (partial xyz)

15:07 raek: msappler: a macro is a function that takes unevaluated code as parameters and return new code

15:07 msappler: your macro does not return new code, but evaluates it during compile-time

15:09 ` ("syntax-quote") is just a way of constructing data structures, especially useful as a kind of code templating language

15:09 so, yes. you are supposed to quote the new code

15:10 (defmacro testmacro ([a b] `(+ ~a ~b)) ([] `(testmacro 1 2)))

15:10 this is eqivalent to:

15:10 (defmacro testmacro ([a b] (list 'clojure.core/+ a b)) ([] (list 'user/testmacro 1 2)))

15:11 devn: partial function application, I would say. "currying" is a related concept, but not exactly the same thing.

15:16 msappler: thank you raek

15:26 tomoj: raek: still, why should it overflow the stack?

15:26 (testmacro 1 2) macroexpands to 3 just fine

15:28 raek: hrm, weird

15:29 tomoj: oh

15:30 the (testmacro 1 2) in the macro definition is inside the macro definition..

15:30 not sure exactly why it overflows the stack, but I wouldn't expect it to work

15:31 raek: reversing the order of the two arities makes it work

15:31 where "works" = does not cause a stack overflow

15:32 tomoj: huh, I still get the overflow

15:32 (defmacro testmacro ([] (testmacro 1 2)) ([a b] (+ a b))) you mean?

15:33 raek: yes

15:33 tomoj: oh, had some weird state left over from the previous definition

15:33 "works" from scratch

15:33 .. no it doesn't. oh well.

15:33 raek: heh

15:34 if I restart the repl, that version stops to work as well

15:34 but if I eval the same code again, it does

15:37 currentB: anyone happen to know of a good guide to clojore metadata?

15:43 ordnungswidrig: currentB: besides the doc on with-meta and meta?

15:51 currentB: what do you want to accomplish?

15:53 rrc7cz: has anyone ever played with haskell-style Either return types for dealing with errors rather than using exceptions?

16:04 shortlord: in cases where both "partial" and #( ) can be used (e.g. (partial * 100) vs. #(* 100 %) ), which one should be preferred?

16:20 replaca: shortlord: I consider it entirely a mater of taste. I will usually use partial there, but it's a fine line

16:20 ordnungswidrig: rrc7cz: in my experience this makes only sense with pattern-matching

16:21 rrc7cz: perhaps together with matchure it might be worth a try. (http://spin.atomicobject.com/2010/04/25/matchure-serious-clojure-pattern-matching)

16:21 shortlord: replaca: ok, thx. I guess I'll use partial then, a bit less parenthesis-nesting

16:22 replaca: shortlord: I think that #() has a tiny performance advantage, by I've never noticed a diff in practice

16:23 LauJensen: shortlord: http://kotka.de/blog/2009/12/Pointfree_vs_Pointless.html

16:27 ordnungswidrig: LauJensen: very good article.

16:27 In general I consider ->> the better style in clojure. For haskell there, e.g. it's a different game because if the $ operator and such

16:27 LauJensen: yea, he's an interesting guy

16:44 clgv: so, for performance: is it better to avoid partial and use alternatives?

16:44 I mean to avoid partial in cases where it is often called

16:45 shortlord: is there any short form for (first (filter pred coll))? Some is similar, but instead of the first logical true value of pred, I need the first item of coll for which pred is true

16:50 amalloy: shortlord: enough people (including me) want that function that it will hopefully be added in future, but currently no

16:51 clgv: if performance is a huge deal, then yeah partial is a little slower

16:52 shortlord: amalloy: ah ok. I'll stick with first and filter then

16:52 clgv: amalloy: ok thanks.

17:18 Berengal: I need some opinions. Which is easier to read and work with: http://hpaste.org/42867/relations

17:19 The lisp, or the sql?

17:20 And ignoring all things meta, like embedding them in programs. Pretend they're both simple query languages

17:21 amalloy: Berengal: the sql looks better to me, but i have experience with sql and none with the clojure-sql libraries

17:22 Chousuke: the problem with the sql query is that you gotta read it inside out

17:22 whereas with the clojure you can just go straight

17:22 amalloy: Chousuke: heh. a funny objection in a lisp channel

17:22 Chousuke: I guess :)

17:26 Berengal: amalloy: This isn't part of any existing clojure-sql library. It's just an experiment I'm doing

17:26 amalloy: ah

17:27 Chousuke: reminds me of the new clojureql

17:27 seems to have a similar idea

17:28 Berengal: Chousuke: Sort of. I think we're solving different, but heavily overlapping problems though. I want to put the relational back in "relational data base"

17:28 Besides, all I'm doing is just an experiment/long-winded, multifaceted kata

17:31 It's hard to beat sql though. It's an excellent language for what it's made for, but with terrible syntax and a few glaring flaws

17:31 LauJensen: Berengal: hehe, you're doing the exact same thing as ClojureQL, exactly

17:33 AWizzArd: LauJensen: btw, I wanted to ask you about the Protocol in ClojureQL. I want to ask a why-question which is by most people understood as criticism. But mine comes from pure curiosity and is not criticism at all :)

17:33 LauJensen: Berengal: You want to put relational back into relational database, and ClojureQLs motto contributed by chouser is "bringing relational algebra back to relational databases" :)

17:33 Berengal: LauJensen: Hah, I must've missed that

17:33 LauJensen: AWizzArd: I like critcism, so dont apologize even before you start flaming

17:34 AWizzArd: LauJensen: Why did you use a Protocol and had the defrecord extend it? Another approach could have been: you have the mere defrecord and make all the implementations defns.

17:34 Note: this is not a suggestion.

17:35 LauJensen: AWizzArd: Eventually, I think the AST will have more interface than RTable, like Joins, Unions etc. Initially I started with this approach simply for the ease of accessing fields

17:36 AWizzArd: Yes, I thought that there may come other defrecords, and from this moment on the defns would be no real option. Plus with your current strategy you make the code a bit shorter (by not having to type out the “defn”s).

17:37 I just did not find any other defrecord so far and that’s why I thought that it could in principle be done without the Proto.

17:37 LauJensen: It could

17:37 Berengal: check out clojureql.org for some examples, I think you'll see the exact same API

17:40 AWizzArd: LauJensen: btw, ClojureQL looks really nice. I am thinking about using it in one of my projects. Does it use prepared statements under the hood, so that I don’t need to worry about injections?

17:41 LauJensen: AWizzArd: Yea, one of the features I most happy about is the automated paramaterization of _everything_. Every value you pass will be set as an object on a prepared statement, so it should be completely safe

17:42 AWizzArd: LauJensen: did you also think about adding cursors? So that one could safely iterate over huge result sets and/or decide to stop processing them at any time?

17:43 LauJensen: Its already there, just add {:fetch-size 50000} to your connection object and your results will be chunked

17:43 devn: I have a map {:a :b :c :d}, and I want to check that :a :b and :c all have fuzzy versions of false ["false", false, 0, "0"]

17:43 most efficient way to write this function?

17:43 AWizzArd: LauJensen: hmm, I see. I need to look into that.

17:44 devn: ,(select-keys {:a "false", :b 0 :c 1} [:a :b])

17:44 clojurebot: {:b 0, :a "false"}

17:44 AWizzArd: devn you can work with select-keys and with (some #{"false" false 0 "0")

17:44 devn: ah yes that's what i was looking for thanks AWizzArd

17:45 Chousuke: or every? :P

17:45 AWizzArd: yes

17:48 devn: ,(every? #(= (val %) #{"false" false 0 "0"}) (select-keys {:a false :b "false" :c 0 :d "0" :e 1} [:a :b :c :d]))

17:48 clojurebot: false

17:48 devn: err that's not right

17:51 AWizzArd: devn: sets can be used as functions

17:52 and put a ‘vals’ around select-keys

17:52 Chousuke: ,(every? #(contains? #{"false" false 0 "0"} (val %)) (select-keys {:a false :b "false" :c 0 :d "0" :e 1} [:a :b :c :d])

17:52 clojurebot: EOF while reading

17:52 AWizzArd: ,(vals (select-keys {:a 1, :b 2, :c 3} [:c]))

17:52 clojurebot: (3)

17:52 Chousuke: you need to use contains? because

17:52 ,(#{false} false)

17:52 clojurebot: false

17:53 AWizzArd: Ah yes, that thing agani.

17:54 Chousuke: ,(every? #(contains? #{"false" false 0 "0"} (val %)) (select-keys {:a false :b "false" :c 0 :d "0" :e 1} [:a :b :c :d]))

17:54 clojurebot: true

17:56 AWizzArd: Though I must still say that I would prefer vals vs. val :)

17:56 LauJensen: this :fetch-size looks interesting, thanks for bringing this to my attention.

17:57 LauJensen: AWizzArd: no problem - just note that its a clojureql specific thing, I dont think anybody else references cursors like that

17:58 devn: that seems so verbose for the problem but maybe im just being OCD

17:58 it seems like you should be able to do the same thing with less but again i think my brain is playing tricks on me

18:05 anyways, thanks for the help

18:12 amalloy: Chousuke, devn: instead of (contains #{} (val)) you can do (comp #{} val), no?

18:13 Chousuke: amalloy: not in this case

18:13 amalloy: thus avoiding any anonymous functions

18:13 oh right, cause false isn't true :P

18:13 laaame

18:13 Chousuke: comp was my first idea too

18:13 AWizzArd: it would kill every? in this case, but normally it would work.

18:14 (every? #{1 2 3} (vals (select-keys map keys)))

20:39 devn: here's another question

20:39 is clojure.string available without a use/require?

20:40 and the answer is of course no :)

20:41 amalloy: *chuckle* indeed, that is of course the answer

20:42 devn: :)

20:42 ,(use 'clojure.string)

20:42 clojurebot: WARNING: replace already refers to: #'clojure.core/replace in namespace: sandbox, being replaced by: #'clojure.string/replace

20:42 WARNING: reverse already refers to: #'clojure.core/reverse in namespace: sandbox, being replaced by: #'clojure.string/reverse

20:42 nil

20:43 devn: ,(join "hello" "world")

20:43 clojurebot: "whelloohellorhellolhellod"

20:43 devn: interesting behavior :)

20:43 amalloy: devn: "world" is a seq of five characters

20:43 you joined them together with hello

20:43 &(require '[clojure.string :as s]])

20:43 sexpbot: java.lang.Exception: Unmatched delimiter: ]

20:43 devn: yes i know i guess i was just a bit surprised at first

20:44 amalloy: &(require '[clojure.string :as s])

20:44 sexpbot: ⟹ nil

20:44 amalloy: &(s/join ["hello" "world"])

20:44 sexpbot: ⟹ "helloworld"

20:45 amalloy: btw it is kinda rude to (use) stuff in the bots if it's going to override other existing functions

20:45 ,(ns-unmap *ns* 'replace)

20:45 clojurebot: nil

20:45 amalloy: ,(ns-unmap *ns* 'reverse)

20:45 devn: the join documentation is weird

20:45 clojurebot: nil

20:45 amalloy: ,(refer '[clojure.core :only [reverse replace]])

20:45 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to clojure.lang.Symbol

20:45 devn: &(join ["hello" "world"] " ")

20:45 sexpbot: java.lang.Exception: Unable to resolve symbol: join in this context

20:46 amalloy: devn: s/join

20:46 ,(use '[clojure.core :only [reverse replace]])

20:46 devn: ,(join ["hello" "world"] " ")

20:46 clojurebot: nil

20:46 " "

20:46 devn: ,(join " " ["hello" "world"])

20:46 clojurebot: "hello world"

20:46 devn: ,(doc join)

20:46 clojurebot: "([coll] [separator [x & more]]); Returns a string of all elements in coll, separated by an optional separator. Like Perl's join."

20:46 devn: now to mean that suggests that you give it a coll followed by a separator

20:47 amalloy: you're reading it wrong

20:47 devn: s/mean/me

20:47 sexpbot: <devn> now to me that suggests that you give it a coll followed by a separator

20:47 amalloy: it takes either ([coll]) or ([separator [x & more]])

20:47 devn: bah im such a newb :(

20:47 tomoj: speaking of that, probably shouldn't be [x & more] there..

20:48 amalloy: tomoj: you could say coll instead, but i don't see much gain

20:48 devn: ,(join " " ["hello", "world"] ["foo" "bar"])

20:48 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (3) passed to: string$join

20:49 tomoj: people looking at the arglists don't need to know join does its work by destructuring

20:49 devn: tomoj: i agree - if that had said [separator coll], i would have never asked this question in the first place

20:49 or found it "odd"

20:49 tomoj: "However, you should only destructure in the arg list if you want to communicate the substructure as part of the caller contract. Otherwise, destructure in a first-line let."

20:53 * devn totally did not know about clojure.repl/apropos

20:53 devn: ,(clojure.repl/apropos #"set")

20:53 clojurebot: (superset? subset? thread-set-name reset-inspector set-pprint-dispatch set-primary set-env-value set-notnull set-env set-system-properties ...)

20:55 amalloy: devn: find-doc too

20:55 &(find-doc "set")

20:55 sexpbot: ⟹ ------------------------- clojure-http.resourcefully/with-cookies ([cookie-map & body]) Macro Perform body with *cookies* bound to cookie-map (should be a map; empty if you don't want any initial cookies). Responses that set cookies will have them saved in the *cooki... failed to gist: Broken pipe

20:55 Raynes: sexpbot: wut

20:55 amalloy: hm. that's...not as pretty as it could be

20:55 Raynes: Broken pipe? Who broke my pipe?

20:55 amalloy: Raynes: isn't that the error he gives if the gist is too long?

20:56 Raynes: amalloy: No. Not unless gist is doing it.

20:56 $(range 1000)

20:56 amalloy: &(repeat 1e6)

20:56 er whoops

20:56 &(repeat 1e6 1)

20:56 sexpbot: Execution Timed Out!

20:56 ⟹ (1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ... failed to gist: Broken pipe

20:56 Raynes: &(range 1000)

20:56 sexpbot: ⟹ (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 ... http://gist.github.com/771336

20:56 Raynes: Yeah, too large.

20:57 * Raynes continues about his business.

21:52 jimdagem: what're you guys talking about?

22:53 GeoffSK: When i (-> 10 (fn [x] (+ 1 x))) ; i get an error, any clues why?

22:58 amalloy: GeoffSK: because (fn 10 [x]) isn't so hot

22:58 try (-> 10 ((fn [x] ...)))

22:59 GeoffSK: no surprise you are right.

22:59 what's the difference between inc and (fn [x] (+ 1 x))

23:00 Raynes: There isn't one.

23:00 GeoffSK: i feel i just met a koan.

23:02 I am perplexed : (-> 1 inc) is good. (-> 1 (fn [x] ...) is bad, but inc and (fn [x] ... ) is the same.

23:02 Raynes: &(macroexpand '(-> 10 (fn [x] (+ 1 x))))

23:02 sexpbot: java.lang.UnsupportedOperationException: nth not supported on this type: Integer

23:02 amalloy: &(macroexpand '(-> 1 (fn [x] (+ 1 x))))

23:02 sexpbot: java.lang.UnsupportedOperationException: nth not supported on this type: Integer

23:03 Raynes: Speaking of bugs.

23:03 amalloy: um

23:03 ,(macroexpand '(-> 1 (fn [x] (+ 1 x))))

23:03 clojurebot: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.UnsupportedOperationException: nth not supported on this type: Integer

23:03 amalloy: apparently it's so broken it can't macroexpand?

23:03 Raynes: Or not.

23:03 Wow.

23:03 amalloy: GeoffSK: the difference is -> is modifying your (fn) form before it gets evaluated

23:03 inc is already written; there's nothing to modify

23:04 GeoffSK: got it.

23:04 macros and fns are interchangeable

23:04 macros and fns are NOT interchangeable

23:04 Raynes: (-> 10 (fn [x] (+ 1 x))) = (fn 10 [x] (+ 1 x)); (-> 10 inc) = (inc 10)

23:05 amalloy: GeoffSK: right, the second one

23:05 GeoffSK: thanks, don't completely grok, but thats my homework. Thanks.

23:08 ok i read the source. Is their a reason it should be a macro rather than fold

23:08 oops i mean reduce

23:09 amalloy: GeoffSK: it needs to be applied before its arguments are evaluated

23:09 GeoffSK: of course.

23:09 Thanks again.

23:09 amalloy: the macro could be written using reduce, if it were desired

23:10 GeoffSK: yes, but like you said, the macro part is critical (code as data)

23:10 amalloy: right

23:20 btw0: what's the best way to generate a random subset with specified number of elments from a set?

23:22 tomoj: anybody see what I'm doing wrong? https://gist.github.com/0e6815afb89d1b5b075e I guessed it was a type-hint problem, but I can't think of any other ways to hint it

23:24 amalloy: btw0: i dunno the best way, but (take n (sort-by (fn [_] (rand)) coll)) would probably work

23:24 tonyl: tomoj: I don't think you would gain much by type hintin void

23:25 tomoj: not trying to gain anything except an instance of the interface

23:25 since two of the methods share name and arity, I think I have to provide all hints

23:26 tonyl: methods don't dispatch by method signature in clojure only by arity so you would have to deal with it differently

23:27 tomoj: you see that I'm reifying?

23:27 btw0: amalloy: that's a nice solution, thanks!

23:28 tonyl: yeah kf which has a method a that has 2 different signatures

23:28 which is a predicament I haven't work with before

23:29 tomoj: &[(.indexOf "foo" 111) (.indexOf "foo" "o")]

23:29 sexpbot: ⟹ [1 1]

23:29 tomoj: don't think that's the predicament

23:30 could there be problems interoping with classes/interfaces in the default package, maybe?

23:30 chouser:

23:30 pardon me

23:32 cemerick: btw0: rand-nth should get you a good way there.

23:32 tomoj: strange, (.a (reify kf) "foo") gives the expected AbstractMethodError

23:33 yet "Can't define method not in interfaces: a"

23:33 btw0: cemerick: you mean run rand-nth against the collection multiple times?

23:33 tomoj: oh shit

23:34 * tomoj slaps self around a bit with a large trout

23:34 tomoj: I just left off the 'this' arg

23:35 tonyl: tomoj: I think you can operate with same named methods and different signature, but once you tried to redefined them in clojure, clojure doesn't work by signatures, but just arity. at least that is what i think

23:35 but if you find something else, let me know, that would open some eyes

23:36 tomoj: works fine with the 'this' param included

23:37 tonyl: updated the gist to show

23:38 tonyl: so including it in the methods works the ambiguity? interesting

23:38 tomoj: you opened my eyes :) that is always welcome

23:38 cemerick: btw0: sure; this is just an example, but should illustrate the idea:

23:38 ,(into #{} (take 10 (repeatedly #(rand-nth (seq (set (range 100)))))))

23:38 clojurebot: #{33 98 67 44 77 15 18 56 91 28}

23:38 tomoj: it's java so we have dispatch by type

23:38 just like my indexOf example above

23:39 cemerick: btw0: certainly don't need the other set in there, but you said you were drawing from a set…

23:39 ,(into #{} (take 10 (repeatedly #(rand-nth (range 100)))))

23:39 clojurebot: #{0 98 7 74 11 19 54 55 89 58}

23:41 btw0: cemerick: isn't the performance really bad if take large number of elements from a relatively small set?

23:43 amalloy: cemerick, btw0: that also includes duplicates

23:45 cemerick: amalloy: yeah, I've no idea what btw0's real use case is, may or may not matter

23:45 btw0: not sure what you mean. If it's doing what you need it to do, then perf/optimization is orthogonal.

23:47 amalloy: btw0: if you want it to be fast and don't care about duplicates, your best bet is probably something like ##(let [elts (vec (range 100))] (take 10 (repeatedly #(rand-nth elts))))

23:47 sexpbot: ⟹ (53 63 45 8 50 23 55 23 29 26)

23:47 btw0: cemerick: actually what i mean is the performance is bad if we need to get rid of duplicates.

23:49 cemerick: since every time there is a dup we need to rand-nth again, this will happen really frequentlly if take a large number from a relatively small set.

23:49 cemerick: btw0: then dedupe the source set/seq/collection once, and take randomly from that result.

23:50 er, source sets are, of course, "deduped" already

23:51 amalloy: cemerick: i think his issue is he wants the result to have no dupes

23:52 btw0: amalloy: exactly

23:52 amalloy: &(into #{} (take 10 (repeatedly #(rand-nth (range 10)))))

23:52 sexpbot: ⟹ #{0 5 6 7 8 9}

23:53 amalloy: is an example of the problem

23:54 btw0: no dupes and no less if the source can provide that many elements

23:54 cemerick: hard to know what to recommend in general -- depends a lot on the data/problem

23:54 dedupe the source collection, shuffle it, and then pop values off?

23:57 btw0: I am afraid shuffling a large collection is slow

23:58 tomoj: how large is 'large'? :)

23:58 btw0: how about 200000?

23:58 tomoj: more importantly I guess, how many times?

23:58 &(time (when (shuffle (range 200000))))

23:58 sexpbot: ⟹ "Elapsed time: 190.16017 msecs" nil

23:58 tomoj: seems slow to you?

23:58 cemerick: tomoj: beat me to it :-P

23:59 tomoj: huh

23:59 &(-> 200000 range shuffle when time)

23:59 sexpbot: ⟹ "Elapsed time: 167.677456 msecs" nil

23:59 tomoj: :)

23:59 cemerick: btw0: in any case, you need to pay the price for randomization and avoiding duplicates somewhere.

Logging service provided by n01se.net