#clojure log - Dec 29 2011

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

4:02 kral: 'morning

4:03 CmdrDats: good morning

4:05 hey guys, i'm starting to use the whole (with-…) paradigm and have written a small (with-mail [config & body]) macro/function that binds *store* to the imap connection which you can then use in body...

4:06 what bugs me though is that *store* is kindof invisible in local scope, you need to know more about the function than just analyzing the signature in order to use it

4:08 ie - i have (with-mail config (print (take 1 (messages *store*))))

4:08 thoughts?

4:29 hoeck1: CmdrDats: as this is a typical 'close-resource-on-leaving-scope' situation, you could also use the builtin with-open macro: (with-open [store (get-connection)] ...code-using-store]) and make sure store has a .close method

4:30 CmdrDats: that would make it more readable by separating the 'close this resource' task and the 'bind resource to X' task

4:31 CmdrDats: ah, nice :)

4:31 didn't realize the with-open worked like that, that's neat

4:33 luckily, this (get-connection) does have a .close - but what if the java object doesn't have .close (say it's .closeConnection or something stupid)?

4:34 hoeck1: sorry - still trying to get used to prepending the name of the person i'm addressing in irc :P

4:34 hoeck1: you would have to write your own close (multi) method then

4:36 CmdrDats: my clojure skills are a bit rusty, I have to google for that first :)

4:36 CmdrDats: hoeck1: busy looking at http://clojuredocs.org/clojure_core/clojure.core/with-open

4:37 hoeck1: can you multi-method the a dotted function like that? having a hard time imagining how

4:37 (looking at the source of with-open

4:37 )

4:39 hoeck1: i suppose i get generate a little (proxy) that has a close method, but that doesn't seem very idiomatic clojure

4:40 hoeck1: yep, the multimethod won't work

4:41 CmdrDats: no, I think creating a proxy or using extend-type is the right way to go, especially when you interfacing with java classes

4:42 otherwise you probably would define your own type and implement the java.io.Closeable interface in the same way

4:43 or define your own interface or protocol that provides a close method

4:44 CmdrDats: hoeck1: awesome, didn't know the Closeable interface existed - i might use that :)

6:31 wei_: is there a version of "some" that returns the actual element, instead of (pred element) ?

6:46 Raynes: (first (filter odd? [2 2 2 1 4]))

6:46 &(first (filter odd? [2 2 2 1 4]))

6:46 lazybot: ⇒ 1

6:46 Raynes: wei_: ^

6:46 wei_: This is no less efficient because filter returns a lazy sequence and you're only asking for the first element.

6:47 wei_: i see, i was wondering whether filter would go through the entire list

6:47 Raynes: Nope.

6:47 No unnecessary computation is done.

6:48 wei_: &(first (drop-while odd? [2 2 2 1 4]))

6:48 lazybot: ⇒ 2

6:48 wei_: &(first (drop-while #(not (odd? %)) [2 2 2 1 4]))

6:48 lazybot: ⇒ 1

6:48 Raynes: &(even? 1)

6:48 lazybot: ⇒ false

6:51 dbushenko: hi all!

7:26 Blkt: good morning everyone

8:17 raek: midje-mode displays some messages like this: ^[[31mFAIL^[[m0

8:17 anyone know how to fix that?

8:18 apparently it tries to use terminal color escape codes in emacs buffers...

10:44 TimMc: raek: I think I remember something about those being added recently...

11:20 kurtharriger: is it possible for leiningen to add extra class paths based on environment variables? :extra-classpath-dirs [(System/getenv "HBASE_HOME")] ?

11:33 TimMc: kurtharriger: Don't tell technomancy I told you this, but you can add arbitrary code to project.clj files.

11:33 so you could probably insert a variable.

11:34 kurtharriger: hmm the above was never evaluated lein classpath | tr ":" "\n" contained (System/getenv "HBASE_HOME") instead of the value

11:34 budu: hi

11:34 kurtharriger: the hbase config folder needs to be in the classpath which works if I use the full path but the above did't

11:35 one workaround I have for now is just to create a symlink to the config directory

11:36 budu: i was wondering about the best way to add a new map type

11:37 for example using the Guava BiMap in the same way as an hash-map or sorted-map

11:37 from my understanding i would need to create a protocol overriding the map functions and dispatch from them

11:38 is that correct or there's something i'm missing?

11:38 TimMc: budu: Is that a persistent data structure?

11:38 budu: yup

11:38 technomancy_: kurtharriger: you can use unquote to add abritrary code, but it's kind of gross

11:39 kurtharriger: ok I'll try it

11:39 :extra-classpath-dirs [~(str (System/getenv "HBASE_HOME") "/" "conf")]

11:39 perfect thanks!

11:40 TimMc: "Var clojure.core/unquote is unbound"

11:40 technomancy_: TimMc: inside defproject

11:40 kurtharriger: maybe later I'll create add a :extra-classpath-env or something

11:41 also does leiningen have any support for compiling languages other than java, namely groovy

11:41 * technomancy_ has a rather low opinion of programs that won't function unless environment variables are set

11:41 TimMc: technomancy_: I think it varies based on where in the defproject.

11:41 technomancy_: TimMc: as long as it's after the version it should be fine

11:42 TimMc: technomancy_: Yeah, I discovered that (defproject adhoc ~(str "1.0." (rand-int 10) "-SNAPSHOT") ...) doesn't work.

11:42 But without the unquote it is fine!

11:42 technomancy_: kurtharriger: if there's an ant task for groovy compilation it should be easy to write one.

11:43 TimMc: oh weird. that's unintentional but kind of funny.

11:43 kurtharriger: is it possible to implement languge additions as plugins or do plugins only allow addition of extra commands to cli

11:44 TimMc: technomancy_: Now I'm imagining using Date there to version a project's releases. :-P

11:44 technomancy_: not sure what language additions means

11:44 kurtharriger: plugins can include defns etc if that's what you mean

11:44 kurtharriger: like :java

11:45 TimMc: kurtharriger: You mean, custom field parsers for the project.clj?

11:45 kurtharriger: if I add :groovy source dir to project have it compile all the groovy classes without having to go through ant to do it

11:45 no desire to write more groovy code just replace gradle with leiningen

11:45 gradle is a POS

11:45 but better than maven

11:46 in some cases

11:49 technomancy_: kurtharriger: what I mean is you could implement a wrapper for ant's groovy compilation using leiningen

11:50 and you could have it trigger on the compile task using a hook

11:50 kurtharriger: ah okay that sounds promising

11:50 technomancy_: look at how the lein-javac plugin is implemented I guess

11:50 kurtharriger: I thought you meant write an ant.xml file and then could call that

11:50 technomancy_: nah, it's all programmatic

11:51 kurtharriger: sounds good then I'll try to do that this weekend if I have time then

11:57 zawzey: ClojureScript question. What's the proper way to create a Javascript associative map object?

11:57 I can only get it to work using (js* "{foo: 'bar', bar: 'foo'}")

11:58 I don't like this approach, but that's the only way to get interop with Javascript code it seems, for an object

12:09 raek: zawzey: I have barely used cljs myself, but I think there is a function called clj->js

12:09 zawzey: well there's a js->clj function

12:09 but no clj->cs

12:10 ibdknox: correct

12:10 zawzey: anyway, there's a solution here: https://gist.github.com/1199718/107cc34620fa3a8284face3c3f7aa4439a565e45

12:11 ibdknox: pinot has a simple map->js function

12:11 zawzey: perhaps same as this: https://gist.github.com/1199718/fb9e16ac1ce261e0dac59db3b2b3c18f1c5f71cc

12:11 thanks i'll check that out

12:13 well it's here: https://github.com/ibdknox/pinot/blob/master/src/pinot/util/js.cljs

12:42 choffstein: Hello all. Quick q: why does conj add to the front of a list and the back of a vector? Is it to try to maintain O(1)? I'm trying to figure out which will be faster to me -- conjing to a list and reversing, or conjing to a vector.

12:43 shales: mrb_bk: have you tried bytebuffer?

12:44 blcooley: choffstein: conjing to a vector should be faster

12:44 choffstein: blocooley: Well, only if conjing to a vector is O(1), right?

12:45 cgray: choffstein: if you are only adding one thing, then both are O(n)

12:45 choffstein: (assuming you are starting with a list)

12:45 zzach: Browser-based REPL from clojurescript is working OK with firefox, but is not connecting to Internet Explorer. Is it in principle possible to use it with IE?

12:45 choffstein: How can conjing to a list be O(n)? You're adding to the front? It should just be a cons...

12:46 arohner: choffstein: correct. They're both O(1), and yes, that's why it's at the front of the list and the back of the vector

12:46 cgray: choffstein: you said conjing and then reversing

12:46 choffstein: arohner: Thanks.

12:46 cgray: I think technically, conjing to a vector is O(\log_{32} n)

12:47 * Raynes hates big o notation.

12:47 choffstein: cgray: Right. I was just saying that if conjing a vector is O(n), then n O(n) operations will be slower than n O(1) operations followed by an O(n) operation

12:47 cgray: choffstein: ahh, i see

12:48 choffstein: Well … maybe the source will tell me?

12:49 blcooley: choffstein: it's discussed in 5.2.4 of JoC

12:49 choffstein: "A small change, but the code is now a touch cleaner and a bit faster"

12:50 choffstein: that's a discussion of conjing to a vector versus conjing to a list and reversing

12:50 choffstein: I'll check it out. Thanks.

12:54 mrb_bk: shales: i did play with it, yes

12:55 shales: are you the author?

12:57 choffstein: blcooley: That answered my questions. I would love to know the big-O notation … but I don't feel like digging through the code :)

13:00 blcooley: choffstein: PersistentVector is here: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentVector.java

13:00 TimMc: &(into () '(1 2 3 4 5))

13:00 lazybot: ⇒ (5 4 3 2 1)

13:02 blcooley: choffstein: it looks like it should be O(1) because it is setting an element in an array. There is the issue of making a copy of the array, but I think you'll find that Lists have the same overhead since it's for immutability.

13:02 choffstein: yeah. Awesome.

13:03 That is helpful. Thanks for poking around

13:03 blcooley: yw

13:04 cgray: blcooley: see line 460 or so

13:04 if the tail is full, it creates a new node in a tree

13:10 choffstein: cgray: Hmm…seems strange to have vector be a tree. I'd expect a dynamic array that doubles in size everytime the end of the array gets hit. The only reason I could see using a tree is so that nth is O(logn) -- but a dynamic array would have nth being O(1) -- so that doesn't make much sense to me

13:10 Though, this Java code isn't very clear to me

13:10 arohner: choffstein: the vector is a tree, so that when you update the middle element, you only copy a constant number of items, rather than the whole tree

13:10 shales: mrb_bk: sorry, was away for a bit. Yeah, I replied to your email on the lsit

13:10 mrb_bk: shales: cool!

13:11 choffstein: Ahhhh … right. Cloning.

13:11 Forgot this was immutable data.

13:11 Okay, the tree makes WAY more sense now.

13:11 mrb_bk: shales: i especially like unpack-bits

13:11 think it would be cool to have in core

13:13 shales: ya maybe. I don't know if anyone other than me or you have used it =)

13:21 mrb_bk: shales: hehe word

13:21 shales: have you used bytebuffer to lazily read from a binary file?

13:24 shales: mrb_bk: no. I've only used it to pull apart and build network packets

13:25 mrb_bk: shales: ah cool

13:25 shales: i was having a hard time getting it to work with files

13:26 shales: what sort of trouble? I imagine you can read chunks of the file into a ByteBuffer and pull what you need from it with the library

13:26 I guess you'd have to be careful how much you read into the buffer if you don't know in advance where the boundaries between fields in the binary data are

13:28 maybe a function that returns the number of bytes needed by one of pack/unpack's format string would be useful?

14:16 kurtharriger: is it possible to reload java class files in clojure ie (import :reload '[com.some.java.package SomeClass])

14:18 TimMc: kurtharriger: Looks like import doesn't take any keyword arguments.

14:18 technomancy: you'd need a new classloader to do that

14:18 kurtharriger: yeah, currently just killing and reloading swank when I recompile the groovy application

14:20 looking to avoid gradle install; lein deps; lein swank... so I just pointed :extra-classpath-dir to my groovy app classes/main folder then I just need gradle compileGroovy and then restart swank

14:21 sjl: #haskell

14:23 gf3: technomancy: ping

14:23 technomancy: gf3: what's up?

14:23 gf3: technomancy: when I install your clojure-swank as a standalone plugin, the generated script contains a hardcoded classpath

14:23 /home/phil/... or something

14:24 technomancy: hm; let me take a look

14:24 gf3: technomancy: http://cloud.gf3.ca/CwsE

14:24 MenTaLguY: hey guys

14:26 I'm wondering, is there a more idiomatic (or at least concise) way to do stuff like: (apply hash-map (map (fn [[key value]] [key (some-fn value)]) some-map))

14:26 cgray: zipmap

14:26 MenTaLguY: basically, take some map and transform the keys in it

14:26 hmm

14:27 kurtharriger: technomancy: I actually had an issue with the shell-wrapper when I tried it not adding the classpath to the resulting shell script so maybe its related

14:27 technomancy: gf3: definitely a bug; can you open an issue?

14:28 gf3: technomancy: sure thing, thank you

14:28 MenTaLguY: cgray: so that would be: (zipmap (keys some-map) (map some-fn (values some-map))) ?

14:28 cgray: MenTaLguY: or more precisely (zipmap (keys some-map) (map some-fn (vals some-map)))

14:28 MenTaLguY: ah yeah, vals, not values

14:28 I guess that's a bit better

14:28 still seems like there should be a more concise way to do it

14:29 technomancy: MenTaLguY: agreed; I'd love a map-keys and map-vals

14:30 blerg: seems like it will always be a less efficient operation b/c of the need to recompute hashes / rebal trees / etc, depending on the underlying data structure

14:30 maybe that's why there's no ready made for it?

14:30 pjstadig: but we're lisp hackers

14:30 we know the value of everything and the cost of nothing

14:31 blerg: :) true dat

14:33 gf3: technomancy: https://github.com/technomancy/swank-clojure/issues/95

14:33 thanks again

14:34 amalloy: (into {} (for [[k v] m] [k (some-fn v)])) is another option, MenTaLguY

14:39 technomancy: processing? without org.clojars? really? =(

14:40 amalloy: technomancy: was lein the first tool nudging clojure in the direction of "group name defaults to artifact name"?

14:41 technomancy: amalloy: it's not unheard of in java-land; particularly with projects that moved from ant to maven.

14:44 pjstadig: i think junit has a project-name-as-group-name

14:51 TimMc: technomancy: What's the problem?

14:52 technomancy: TimMc: processing is a language and drawing toolkit; someone either published a random one-off fork of it on clojars masquerading as the original or is really bad at picking names and happened to collide.

14:52 TimMc: What are the semantics of using org.clojars.foo/*?

14:53 Does that just mean "this is my local fork"?

14:53 s/local//

14:54 technomancy: right

14:54 raek: TimMc: yes. foo's personal fork.

14:55 TimMc: Where org.clojars.foo is just some namespace that the user owns, yeah?

14:55 So org.timmc would be equivalent.

14:55 amalloy: that seems unnecessarily specific. you can have a personal fork with a different name, or use org.clojars.foo/libname as the canonical name because you disagree with the libname/libname pattern

14:56 technomancy: it's a matter of communicating to potential consumers

14:57 pjstadig: and presumably there's a way to manage transitive dependencies that you want to use org.clojars.foo/libname instead of what the real group is?

14:58 technomancy: no, unfortunately you need to use exclusions

14:58 there's really no good existing solution for nonlinear versioning in dependencies

14:58 in any language

15:08 cemerick: technomancy: so, does easy s3 deployments from lein mean we can close the book on e.g. org.clojars.name/foo?

15:56 TimMc: cemerick: Why would that be?

15:56 blakesmith: Is there an easier way to convert keywords to their string representation without the leading colon?

15:56 &(apply str (drop 1 (str :hello)))

15:56 lazybot: ⇒ "hello"

15:57 emezeske: &(name :hello)

15:57 lazybot: ⇒ "hello"

15:57 TimMc: cemerick: There are plenty of things on clojars that aren't personal projects.

15:57 blakesmith: emezeske: Perfect, thanks!

15:57 emezeske: blakesmith: NP

15:57 TimMc: $findfn :name "name"

15:57 lazybot: [clojure.core/name]

15:58 cemerick: TimMc: My understanding is that org.clojars.name groupIds should only be used for private forks of projects. Making it hard for others to find such artifacts is a good default, IMO.

15:59 quizme: why does the handler function of the ring tutorial need to be a var?

16:01 cemerick: quizme: it doesn't need to be, but providing a var allows changes you make at the REPL, etc. to be available without restarting the HTTP server.

16:02 quizme: cemerick i see thank you

16:03 cemerick: so it sort of makes it like a "global" across different threads(?)

16:03 technomancy: cemerick: well the stuff I added was really only for private deploys

16:03 you've been able to do public s3 deploys since forever; it's just a matter of docs

16:04 chouser: well, I finally pushed TractionSVG out there, for anyone interested: https://github.com/chouser/tractionsvg

16:04 technomancy: cemerick: I think in most cases putting them on your own s3 bucket is better for clutter reduction, but I want to wait till I've solved the nasty chicken/egg problem before switching all lein's docs to recommend that approach.

16:05 cemerick: technomancy: sure; I'm agitating. ;-)

16:05 quizme: all vars are "global" across threads :-)

16:05 (except for those created with `with-local-vars`)

16:06 technomancy: hush

16:07 hiredman: chouser: neat

16:08 technomancy: ,(alter-meta! #'with-local-vars update-in [:doc] (partial str "Warning: don't use this unless you know what you're doing.\n"))

16:08 clojurebot: {:macro true, :ns #<Namespace clojure.core>, :name with-local-vars, :arglists ([name-vals-vec & body]), :added "1.0", ...}

16:08 technomancy: holy crap; that worked

16:08 not sure how I feel about that

16:09 hiredman: might want to take a look at that. =)

16:10 chouser: hiredman: thanks. It certainly doesn't rate more than that yet.

16:11 all named vars

16:15 choffstein: Hey all. I've read that to speed up your clojure code, you should try to make as few "intermediate" objects as possible. In an iterative version of the code base (in Ruby), I iterate over data and mutate values in place, where computations rely on data computed in previous iterations. In clojure, I end up `mapping` over the data for the different computations I need, then combining them at the end. This seems to create a lot of

16:15 unecessary objects. If I really want to speed it up, should I just go transient and use a reduction style loop? I've already done as much type-hinting and profiling and algorithm restructuring as I think I can -- and the ruby code still seems to about about 1.5-2x faster.

16:16 technomancy: choffstein: transients will help if the slowness is caused by GC

16:16 until you profile you're in the dark

16:17 that said, if you're 2x slower than ruby it's likely to be something a bit more obvious

16:17 are you letting the JIT warm up and excluding JVM boot time?

16:17 choffstein: Hmm. My profiling skills with JVisualVM are still beginnerish. Know if I can see how the GC is behaving

16:17 Not really letting the JIT "warm-up" per-se … just yes on excluding JVM boot time

16:19 cmeier: chouser: thumbs up for tractionsvg

16:20 * technomancy has never done any profiling himself; sorry

16:20 tmciver: chouser: tractionsvg looks very cool

16:26 choffstein: Oh, wow -- I did a dotimes and let the JIT warm up. The clojure code sped-up by almost 4-5x. Yikes.

16:26 The majority of the code is still taken up my invokeMatchingMethod though. Arg. As far as my code tells me, all the reflections are in other libraries...

16:28 technomancy: ouch

16:29 choffstein: did you get a chance to try out https://github.com/heroku/heroku-buildpack-clojure/tree/private-repo?

16:29 choffstein: Yeah! It's awesome!

16:29 technomancy: excellent

16:29 choffstein: I thought I had PMed you. My apologies if I didn't. You're a life-saver. Awesome solution to my problem

16:30 technomancy: no worries; my bouncer isn't 100% reliable, so PMs are sometimes lost.

16:30 choffstein: I had a little clojure app up using redis, resque, background workers and mongodb in like … 6 hours. It was unbelievable.

16:30 technomancy: how do you like resque?

16:31 solussd: technomancy: could you point me at current instructions on how to install swank-cljure/slime-clj/clojure-mode, etc with the emacs-starter-kit? I've had this set up on my personal machine forever, but can't seem to get things going at work-- running M-x package-install with the various packages fails or complains that <whatever> already exists. :/

16:32 technomancy: solussd: I think the swank-clojure readme has everything you need. you can do a manual install of clojure-mode if the package manager is giving you grief.

16:32 TimMc: technomancy: hiredman has known about alter-meta! being allowed since forever. *shrug*

16:32 solussd: technomancy: oh, so I shouldn't install swank-clojure via elpa?

16:32 TimMc: I think that's why clojurebot restarts every 15 minutes.

16:33 technomancy: solussd: yeah, that is way out of date

16:33 choffstein: What amazes me is that in running my huge program like … 50 tims, invokeMatchingMethod takes 99.99999% of the time with only 144 invocations.

16:33 technomancy: solussd: clojure-mode is the only thing required on the elisp side these days

16:34 lypanov: choffstein: accumulative?

16:34 choffstein: lypanov: Sorry, I don't understand the question

16:35 lypanov: choffstein: just wondering if the profile output is inclusive or exclusive.

16:36 choffstein: lypanov: inclusive or exclusive of what?

16:36 * lypanov doesn't have a clue :P only started coding clojure a week back just throwing out ideas

16:36 mcrittenden: do I have to install maven to get clojure contrib?

16:37 lypanov: choffstein: time, i assume invokeMatchingMethod is the caller. if its inclusive then 99.999 makes sense.

16:37 just ignore me :)

16:37 * lypanov is in the weird position of knowing basically no clojure but using clojurescript in production

16:37 choffstein: lypanov: oh. Yeah, I think invokeMatchingMethod is the caller and it is inclusive.

16:38 It measures "self time"

16:42 AeroNotix: anyone used clojure with minecraft?

16:43 cemerick: AeroNotix: I've seen blog posts where those words were in proximity. No idea if they were any good or interesting though.

16:43 TimMc: Yeah, I built a JVM using redstone.

16:43 AeroNotix: TimMc: LOL

16:43 TimMc: About as memory efficient as well?

16:45 TimMc: Actually, I've never played the game.

16:48 skelternet: I think I'm doing it wrong.

16:49 Somelauw: What is the quickest way to just make use of all functions in clojure.string? Something like (import clojure.string)?

16:49 TimMc: Somelauw: (require '[clojure.string :as s])

16:50 Somelauw: or (use '[clojure.string :only (foo bar etc)])

16:50 quizme: Somelauw: (use 'clojure.string)

16:50 TimMc: quizme: Bad!

16:50 Only use use with only*

16:51 * Except clojure.test and the namespace under test in your test files.

16:51 hiredman: a use like that is not the best idea

16:52 clojure.string may have some functions that are the same name as clojure.core

16:52 (require '[clojure.string :as str]) or (:require [clojure.string :as str]) in your ns form

16:52 skelternet: Should I be using a protocol to bundle up various related functions , each of these bundles a particular implementation of a known set of abstract functions? Doesn't that sound like a protocol? or should I relax and toss a bunch of curried functions into a map. That seems ugly.

16:52 Somelauw: Thanks, it works

16:54 I think directly using "use" is useful when testing it in a repl.

16:55 TimMc: Oh yeah, the REPL is a fine place for it.

16:58 skelternet: I'm expecting to have to swap out the implementations based on user-specified configuration

16:59 technomancy: skelternet: if you use a protocol you'll be forced to dispatch on the first argument of every function. if that will result in an awkward API and you don't need crazy-fast dispatch, you probably shouldn't use protocols.

17:00 multimethods are a bit slower but can dispatch on anything; doesn't even have to be an argument

17:00 skelternet: I will be concerned about performance later, after I measure it and discover I am concerned about it. For now, I'd like a clean API to speed development.

17:01 technomancy: very few things in practice are bottlenecked on method dispatch (modulo reflection, which is easy to solve anyway)

17:01 skelternet: My main concern is not wanting to change the client code.

17:04 clojure's given me several options that satisfy that.

17:05 I started down the protocol route since it seems like the most likely to satisfy separating the implementations of this API from the API and it's clients.

17:07 it is familiar behind the scenes: Java interfaces. but more involved.

17:07 hiredman: I have a macro somewhere, that lets you write something that sort of looks like a multimethod, that generates a static cond + a check to see if the static cond is still valid

17:08 and falls back to a multimethod if the static cond isn't valid

17:08 it is ugly

17:09 mcrittenden: TimMc: does the "only use 'use' with 'only' rule apply here: https://github.com/ibdknox/Noir-blog/blob/master/src/noir_blog/views/blog.clj#L2

17:17 mdeboard: Anyone have an idea off-hand where to find a quote rhickey made that I cannot recall about performance not mattering if your data wasn't reliable?

17:18 emezeske: Boy I wish Clojars had a field for linking to the repo from which a jar was built...

17:18 I might need to work up a patch for that

17:18 skelternet: data not reliable as in quality or not always available, as in waiting to come back from storage?

17:18 scottj: emezeske: :url in project.clj?

17:18 pandeiro: mcrittenden: i think 'only use use with only' is only enforced in ClojureScript

17:18 emezeske: scottj: awesome!

17:19 scottj: that just needs to be on the web UI somewhere

17:19 scottj: emezeske: it is displayed if that's what you mean

17:19 emezeske: but if it were in instructions or some way to make it more popular might be nice

17:20 emezeske: scottj: ah, I guess most projects must not fill it in then

17:20 scottj: including mine X_X

17:20 time to fix

17:21 ordnungswidrig: emezeske: one should crawl clojars and send warnings to the owners of projects without url.

17:21 emezeske: ordnungswidrig: I love that idea

17:21 Also, what's up with people having their open-source projects depend on random jars that are not hosted anywhere? PAIN

17:22 ordnungswidrig: emezeske: drop from clojars ;-)

17:22 scottj: emezeske: getwoven?

17:22 emezeske: *the source code for which is not hosted anywhere

17:22 scottj: what's that?

17:23 technomancy: emezeske: wouldn't hurt to have it filled out as a FIXME in the default project.clj emitted by lein

17:23 easy pull request; hint hint

17:23 scottj: emezeske: a team that sometimes does that

17:23 emezeske: scottj: ahh, gotcha

17:23 technomancy: :) adding to my list

17:26 ordnungswidrig: which hash functions does assoc/PersistentArrayMap use?

17:26 object/hashcode?

17:27 scottj: technomancy: do you prefer "FIXME: project url" or ""?

17:28 or write url

17:28 TimMc: http://www.example.org/FIXME

17:28 technomancy: scottj: probably best to leave it commented out; something like ;; :url "http://FIXME"

17:28 amalloy: no, link it somewhere really offensive so they're incentivized to fix it

17:28 technomancy: amalloy: early versions of hoe (a ruby gem generator) attributed all libraries to the author of hoe

17:29 but he got sick of all the bug reports

17:29 ordnungswidrig: technomancy: hehe

17:30 TimMc: hoist in his own petard

17:30 scottj: technomancy: pull sent

17:30 TimMc: s/in/with/ I guess

17:31 technomancy: scottj: excellent

17:31 ordnungswidrig: I once returned from holidays to notice 1e5 new emails in my inbox. Now I stay away from mail-sending logging handlers.

17:31 scottj: technomancy: I'd wanted this for a long time but figured you'd considered and rejected it :)

17:31 technomancy: emezeske: if you still want to get a patch in (which qualifies you for commit access as well as a sticker) you could backport scottj's commit to the 1.x branch =)

17:32 scottj: ordnungswidrig: some dude once returned from holidays to find 3e6 of his emails posted on bittorrent

17:32 technomancy: I'll be collecting my sticker on seajure next week :)

17:32 ordnungswidrig: scottj: bittorrent ist the new imap.

17:33 hiredman: ordnungswidrig: on 1.4-SNAPSHOT it uses a custom hash function, which in most cases falls back to .hashCode

17:34 * lypanov hits sonatype.org

17:34 lypanov: (502s yay)

17:34 emezeske: technomancy: I might get to it!

17:35 technomancy: scottj: uh oh... I may be out of stock.

17:35 been meaning to order a fresh batch with the high-res image

17:37 ordnungswidrig: hiredman: I was just wondering because of this http://events.ccc.de/congress/2011/Fahrplan/events/4680.en.html

17:37 scottj: technomancy: no worries

17:38 technomancy: sticker 2.0 for new release

17:39 hiredman: ordnungswidrig: yeah, I don't imagine rich moving fast on that

17:40 ordnungswidrig: hiredman: in a web context: easy to fix for request headers but hard to check request bodies that are parsed as json/xml and like that I suppose.

17:41 hiredman: *shrug*

17:42 the report I saw mentioned web requests, but really any kind of transport would do

17:42 most message queues get used to more or less pass around maps

17:42 ordnungswidrig: unix comes to help by limiting processing time. But the monolithic java servlet model is a burdon here.

17:43 hiredman: uh

17:43 ordnungswidrig: limiting thread runtime in java, anyone?

17:43 hiredman: really?

17:43 ordnungswidrig: one cannot, right?

17:54 scary: ,(let [l 10 s (apply str "bB" (repeat l "a"))] s (for [i (range l)] (let [s (apply str (concat (take i s) (drop i s)))] [s (.hashCode s)])))

18:00 kd4joa: I was wondering if anyone could help me with a problem I'm having trying to use the Lucene java library. It seems like an easy question, but I'm not finding the answer

18:01 I have an object that is a TokenStream. I have to call incrementToken() on it in order to get all the tokens from the string one at a time

18:01 each time that is called I need to get the value of that token from a TermAttribute object using its term() method

18:02 question is how to call incrementToken() until it's false, gather up all the tokens and create a vector out of them

18:03 I tried doing it in a "while" and can get at the tokens inside the while, but it of course returns nil and I can't figure out how to collect the terms up.

18:03 can someone point me in the right direction?

18:03 hiredman: (repeatedly #(doto ts .incrementToken .getTermAttribute))

18:03 amalloy: hiredman: .getTermAttribute goes outside the doto, right?

18:03 raek: kd4joa: one basic way is to use loop and recur. keep the collection of tokens that you build up as one of the loop variables

18:04 hiredman: amalloy: I have no idea

18:04 http://lucene.apache.org/java/3_0_3/api/all/org/apache/lucene/analysis/TokenStream.html

18:05 kd4joa: your best solution is to write something like enumeration-seq which takes a tokenstream and turns it into a lazy seq

18:05 amalloy: heh. well, i don't either; his description is obviously not very clear. but i was thinking more like (map #(.getTermAttribute %) (take-while identity (repeatedly #(.incrementToken ts))))

18:06 kd4joa: sorry. how can I help make it more cleaer

18:07 raek: kd4joa: when .incrementToken returns true, what do you need to call to get the token?

18:08 kd4joa: (.term termatt) will give me the token (termatt is a TermAttribute)

18:08 here's a working function that prints the token each time through the while: https://gist.github.com/1536626

18:10 raek: kd4joa: I would make a lazy sequence like this: https://gist.github.com/1536636

18:10 clojurebot: Pardon?

18:11 ordnungswidrig: kd4joa: comment written

18:11 kd4joa: simple fix using a atom a temp result holder.

18:12 I don't feel too dirty bacause the java objects already are mutable as hell

18:12 kd4joa: heh, no kidding

18:12 raek: kd4joa: a non-lazy variant: https://gist.github.com/1536637

18:12 kd4joa: thanks to both of you. both approaches look like they should work

18:13 raek: ordnungswidrig: no need to use the concurrency primitives when you can use simple recursion in this case

18:13 kd4joa: thanks. I had started looking at atoms (never used them before), but it seemed like there should be an easier way

18:13 amalloy: (take-while identity (repeatedly #(when (.incrementToken tokenstream) (.term termatt))))

18:15 kd4joa: what makes repeatedly stop there? I thought it returned an infinite sequence

18:16 amalloy: (take-while ...)

18:17 raek: it would be neat to have a "unfold" ("unreduce?") in clojure.core

18:17 kd4joa: hmm. I'll have to play with that a little to understand it

18:17 amalloy: raek: maybe. i implemented unfold, and it seems like i've never found a case where using it was simpler or easier than not using it

18:18 kd4joa: thanks to all of you for the pointers. It'll take me a bit to understand each of the different approaches. So much to learn...

18:18 hiredman: (fn f [ts ta] (lazy-seq (when (.incrementToken ts) (cons (.term ta) (f ts ta)))))

18:20 jhirn: What's the quickest way to move a file from one path to another creating the directories if needed?

18:20 TimMc: quickest to type?

18:20 rsync

18:21 jhirn: =), prefer to keep it java'ish for cross platform.

18:21 hiredman: http://docs.oracle.com/javase/1.4.2/docs/api/java/nio/channels/FileChannel.html#transferTo%28long,%20long,%20java.nio.channels.WritableByteChannel%29

18:21 jhirn: was shelling out to mv,

18:21 but need to mkdir -p... then i figured there might be a move-file somewhere.

18:22 hiredman: you'll need to call .mkdirs on the target files parent directory yourself

18:22 technomancy: .mkdirs on j.i.File is mkdir -p

18:22 oops; too slow

18:23 hiredman: but transferTo or transferFrom should be faster than anything else on the jvm

18:23 jhirn: Ah, so I must creat files... I need mv -p like a mofo right now.

18:23 hiredman: create files?

18:23 jhirn: moving from one place to another.

18:23 for a git utility i'm working on to make renames out of delete/new pairs.

18:24 was doing a simple , reset-> mv -> git mv but mv is failing due to directory not being there.

18:24 i supposed it's easy enough to shell out a mkdir -p

18:25 then that whole dot the right thing started conflicting with the right now thing....

18:33 hiredman: chouser: it would be neat if analemma could be used to generate traction svgs

18:33 https://github.com/liebke/analemma

18:35 solussd: what's the best way to convert a record into a hash-map? currently I use (into {} (vec my-record))

18:38 sandbox: hello, is this a place to ask questions about clojure?

18:39 amalloy: well, that's one so far. i guess the answer must be yes

18:45 sandbox: sorry i was just wondering about namespaces. in particular how do i add functions to an already existing namespace, and is it good practice to do that in project

18:45 when i don't intended to add that function to the library later

18:51 technomancy: sandbox: yeah, definitely don't want to change namespaces you don't control

18:59 sandbox: okay that helps. what i'm still wondering is how to do what is done in clojure/core (defines the namespace) and clojure/core_deftype.clj (uses in-ns to add more to core). i'm getting a "unable to resolve symbol: defn" error when trying to add functions to another namespace. i'm guessing there is something wrong with my build settings but i'm not exactly sure what

18:59 technomancy: the stuff done by core_deftype.clj shouldn't ever be done in user code

19:00 it gets a pass because it has to bootstrap a bunch of crazy stuff

19:05 sandbox: okay that makes that clear thanks

19:12 flognikr: sandbox: have you looked into Clojure's protocols as a mechanism for extending types?

19:17 sandbox: i wasn't dealing with any type but wanted to add a function to a namespace that wasn't mine because it seemed to make sense to put it in that particular namespace. i'm just building a simple web app, using noir, and in noir.response they've defined some functions for different types of responses. i just wanted to add a response that added some things to the header

19:21 flognikr: sandbox: ok, that helps me understand your use case better.

19:21 sandbox: i should have probably started with that information sorry if it was unclear

19:23 flognikr: sandbox: no problem at all

20:31 fryguy: what do people prefer for REPL in vim? slimv or VimClojure?

20:32 devn: i think most everyone i know uses vimclojure

20:52 technomancy: http://p.hagelb.org/slime-compile-presave.el.html

20:52 ^ so this hook will attempt to compile the current buffer when you save and refuse if it doesn't compile

20:52 is this awesome? [y/n]

20:53 Kowboy: y

20:54 now I just wish I could get M-x clojure-jack-in working on NT Emacs so I can use it at work ;-P

20:54 I use Ubuntu at home though (a proper emacs system), so I'm happy here ;-)

20:56 In general, what is the status of clojure contrib for 1.3? I see someone has moved clojure.contrib.http.agent into clojure.contrib.io, but it's not in any public repo yet.

20:57 or is there a better/alternative lib I should be using for HTTP requests?

20:57 hiredman: clj-http

20:57 technomancy: and clojure.java.io

20:57 hiredman: https://github.com/dakrone/clj-http

20:58 technomancy: err--misread that

21:21 augustl: hi folks. Is leiningen the de facto way of managing clojure projects? I'm new to the jvm and java and compiled languages in general

21:21 TimMc: yep

21:22 augustl: TimMc: thanks :)

21:22 TimMc: augustl: You may see references to Cake here and there, but it is being merged into Leiningen, sort of.

21:25 augustl: TimMc: ah, I see

21:26 Leiningen seems simple enough. Just created a project, unlike maven it didn't download the internet

21:27 amalloy: lein uses maven, so you'll be getting some internet before long

21:27 but clojure has very few (zero?) dependencies, so you just need the jars you're using yourself

21:28 augustl: ah

21:29 emezeske: Hmm... I have a project that works fine when I run it with 'java ...' (specifying lib/ as my classpath, etc), but explodes in mysterious ways when run via 'lein run'.

21:29 Anyone have any tips on where to start on debugging such a problem?

21:30 (I should add that to make the 'java ...' invocation work, I add "(apply -main *command-line-args*)" to my main source file)

21:42 TimMc: emezeske: What is one of the mysterious ways?

21:42 Maybe there's some AOT difference.

21:43 emezeske: TimMc: Exception in thread "main" java.lang.RuntimeException: java.lang.AssertionError: Assert failed: Can't recur here

21:43 That's coming out of the clojurescript compiler

21:43 TimMc: Ah, I've seen that!

21:44 emezeske: Yeah, I see some references to it on the noir lists

21:44 But I don't see any solutions

21:44 TimMc: Let me chcek my logs...

21:44 emezeske: Thanks!

21:45 pandeiro: damn my swank is broken again

21:46 TimMc: emezeske: Ah yes, when I was hacking on try-cljs. For a while, the first evaluation would throw that assertion error, and all subsequent evals would succeed (until restart.)

21:47 And now it doesn't do it. -.-

21:47 emezeske: Yeah, it's throwing that error when compiling core.cljs

21:48 After it's compiled, I think the js output is cached and used again (hence no error on try 2)

21:48 pandeiro: "error in process filter: symbol's function definition is invalid: slime-output-buffer"

21:48 emezeske: For me, it never fails when I run via "java ...", and always fails under "lein run"

21:49 I'm guessing it's some kind of weird class loading thing

21:49 pandeiro: weird part is i get the success message (Take this REPL brother etc), but no *slime-repl* buffer

21:49 TimMc: emezeske: Well, throw in a memoized (try compile (catch ...)). :-P

21:50 emezeske: Hah! :)

21:50 I'd actually consider doing that, but for me it fails 100% from lein run

21:50 Even the second time..

21:52 TimMc: emezeske: So, if you (do (try (compile-stuff) (catch ...)) (compile-stuff)) it fails on the second one too?

21:52 emezeske: TimMc: I think so, checking right now to be certain

21:53 TimMc: yep, that fails too

21:54 TimMc: Fascinating.

21:54 emezeske: with the same error

21:55 The thing that's really throwing me off is that things fail in the same way if I create an uberjar and run that

21:55 I'd think that would run things very closely the same way as when I run "java ..."

21:56 DerGuteMoritz: hello everyone, how can I use one of the eval bots in here? I'd like to get feedback on something

21:57 TimMc: emezeske: I can't reconcile that with what I was seeing, but I bet it's an AOT-ish thingy.

21:57 * TimMc blames AOT because he doesn't understand it

21:57 emezeske: TimMc: Yeah, that sounds probable. Thanks for your input!

21:58 Yeah... I don't either. I moved as much stuff as possible out of my (:gen-class) namespace to hopefully avoid problems :P

21:58 TimMc: It's infectious though, right?

21:58 emezeske: Ah, I did not know that

21:58 TimMc: I don't either.

21:59 I just *think* it.

21:59 emezeske: haha

21:59 tmciver: DerGuteMoritz: comma as first character followed by valid Clojure:

21:59 ,(+ 2 2)

21:59 clojurebot: 4

22:00 DerGuteMoritz: tmciver: ah, thank you

22:00 so there:

22:00 ,(symbol? (symbol "123"))

22:00 clojurebot: true

22:00 DerGuteMoritz: ,(symbol? (read-string (pr-str (symbol "123"))))

22:00 clojurebot: false

22:00 DerGuteMoritz: is this a read/write inconsistency or am I missing something?

22:02 tmciver: DerGuteMoritz: looks like pr-str is just producing "123", which is not a symbol?

22:02 DerGuteMoritz: tmciver: that's right

22:03 TimMc: DerGuteMoritz: Sort of. That round-trip is only valid for literal expressions, I believe.

22:03 Since '123 is 123...

22:04 DerGuteMoritz: seems like there is no external representation for symbols which consist of digits only

22:04 TimMc: Correct. That's because symbols are supposed to name things.

22:05 and names are restricted to a certain set of characters.

22:05 DerGuteMoritz: symbols containing spaces are even worse

22:05 ok then the symbol function should reject such strings

22:05 amalloy: "should" is a strong word

22:05 TimMc: There's a forward-compatibility problem there.

22:06 DerGuteMoritz: "must" is even stronger :-)

22:06 amalloy: the expectation is that (pr-str (read-string x)) results in x - if your input to pr-str can never be a valid result from read-string, it's not reasonable to expect read-string to be able to read it back

22:07 TimMc: Hmm, that's right -- there are two round-trips possible.

22:07 amalloy: (read-string (pr-str x)) resulting in x is a much more difficult task

22:07 and all over the language that fails. ##(pr-str (java.util.Date.)) sure can't be read back in

22:07 lazybot: ⇒ "#<Date Thu Dec 29 19:08:49 PST 2011>"

22:08 DerGuteMoritz: amalloy: that's right, but the reader will error on that one

22:09 hmmm

22:09 amalloy: so? the requirement (and here i'm inventing requirements, these aren't in the API docs afaik) is that (pr-str (read-string x)) "works". if you try to do something else, behavior is undefined. sometimes exception, sometimes unexpected output, sometimes explosions

22:09 DerGuteMoritz: agreed

22:09 amalloy: if clojure had to babysit and hand-hold every time you called the symbol function, or the keyword function, or the...things would slow down

22:10 tmciver: read-string is typically used to read a string of valid Clojure to be passed to eval, yes?

22:10 DerGuteMoritz: tmciver: it just reads a datum from a string, you can do with it whatever you want

22:12 amalloy: it just seemed inconsistent to me but I agree that since you can't read in a symbol consisting of numbers or spaces it doesn't have to be possible to write them out, too

22:12 TimMc: DerGuteMoritz: It used to bug me a bit that nil can't be a symbol: ##(map class '[nil true foo])

22:12 lazybot: ⇒ (nil java.lang.Boolean clojure.lang.Symbol)

22:12 DerGuteMoritz: hmmm indeed

22:13 ,(name 'nil)

22:13 clojurebot: #<NullPointerException java.lang.NullPointerException>

22:13 DerGuteMoritz: :-/

22:13 TimMc: That's not true in Scheme, where #t and #f are the boolean literals.

22:13 DerGuteMoritz: ,(name (symbol "nil"))

22:13 clojurebot: "nil"

22:13 DerGuteMoritz: something seems off there

22:14 TimMc: yeah, I'm coming from Scheme which is why I'm kind of used to these kinds of edge cases being specified :-)

22:14 amalloy: what is your take on the nil issue?

22:15 amalloy: it's kinda weird

22:15 DerGuteMoritz: looks like an implementation detail shining through

22:16 amalloy: meh. what is (true false)? is it a list of two symbols, which happen to refer to booleans, or is it a list of booleans?

22:17 DerGuteMoritz: amalloy: depends on the quoting

22:17 ah, same issue here:

22:17 ,(name 'true)

22:17 tmciver: right, how's the reader to know if you meain your symbol nil or the value nil?

22:17 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.Named>

22:17 TimMc: DerGuteMoritz: Not implementation, it's a philosophical diff.

22:17 DerGuteMoritz: tmciver: well, how does it know in this case: (list 'list)

22:18 amalloy: uhhh, because list is not a language primitive with a special type

22:18 TimMc: DerGuteMoritz: You're never going to name something "nil", "true", or "false". Symbols are for naming things.

22:18 amalloy: it's an ordinary symbol, naming a function defined in clojure.core

22:18 DerGuteMoritz: TimMc: special cases ...

22:18 TimMc: Yeha, I know.

22:19 It took me a while to be OK with it.

22:19 tmciver: DerGuteMoritz: flierting with disaster

22:19 DerGuteMoritz: amalloy: yes, and when quoted it is just that symbol

22:19 tmciver: hm?

22:20 amalloy: DerGuteMoritz: so what's your point? list is a symbol, true is a boolean. they behave differently unquoted, and they behave differently quoted

22:20 tmciver: DerGuteMoritz: why would you ever need to name your symbols nil, true or false? Sounds like a problem waiting to happen.

22:20 amalloy: they look "similar" to our eyes because they're made up of letters

22:20 DerGuteMoritz: why does 'true resolve to the boolean true value but 'list not resolve to the list function?

22:20 amalloy: but 4 behaves just the same as true, in all of these cases

22:21 TimMc: tmciver: My only concern is automatic code generation, but we have gensym to take care of this stuff.

22:21 DerGuteMoritz: tmciver: it's a question of consistency rather

22:21 amalloy: DerGuteMoritz: when you quote a literal, you get that literal back

22:21 TimMc: DerGuteMoritz: Compare all this with (4) vs. '(4) vs. [4] vs. '[4].

22:21 amalloy: &['4 'true 'nil 'list]

22:21 lazybot: ⇒ [4 true nil list]

22:21 DerGuteMoritz: it's a matter of special cases

22:21 amalloy: DerGuteMoritz: you can say that all you want

22:22 the "special case" is that you want every sequence of letters to be a symbol, and some of them aren't

22:22 sad, perhaps, but true, and no further inconsistencies arise once you get past that

22:22 DerGuteMoritz: sure, it's just a matter of getting used to and avoiding the edges

22:25 technomancy: there was a ticket open back in the google code days for symbol and keyword to enforce readability

22:25 DerGuteMoritz: technomancy: interesting, do you know how it was resolved?

22:26 technomancy: I patched it, and the patch was ignored

22:26 which started a long tradition

22:27 DerGuteMoritz: of people creating the same patch over and over again? :-)

22:27 pandeiro: technomancy: did swank-clojure 1.3.2 also place a swank folder in .emacs.d/ with the compiled slime files?

22:27 technomancy: pandeiro: I think that was new in 1.3.3

22:29 amalloy: of people ignoring technomancy's patches, i assume

22:30 kenth: I'm on the macro chapter in JoC, what does ~@ do?

22:30 DerGuteMoritz: perhaps technomancy didn't fax in the paperwork

22:30 amalloy: &(let [x [1 2 3] y [4 5 6]] `(~@x ~y))

22:30 lazybot: ⇒ (1 2 3 [4 5 6])

22:31 DerGuteMoritz: kenth: if you know scheme: it's the same as unquote-splicing

22:31 tensorpudding: ~@ splices a list

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

22:31 tensorpudding: well, a collection

22:33 DerGuteMoritz: hm, can somebody explain this:

22:33 ,['foo]

22:33 clojurebot: [foo]

22:33 DerGuteMoritz: `[foo]

22:33 ,`[foo]

22:33 clojurebot: [sandbox/foo]

22:33 DerGuteMoritz: why is the symbol resolved with `? is it because ` is meant to be used for syntax only?

22:34 s,resolved,qualified,

22:35 ldh: i've got a map (data structure) which i process with map (function), which produces a lazy seq of MapEntry. how can i turn that back into a map?

22:35 DerGuteMoritz: if so, is there a syntactic way to splice a list or vector of symbols outside of macros then?

22:35 technomancy: ldh: (into {} (map f x))

22:35 ldh: technomancy: ah, thanks

22:36 DerGuteMoritz: (a list of unqualified symbols, obviously)

22:37 technomancy: DerGuteMoritz: syntax-quote can be used outside macros

22:37 DerGuteMoritz: technomancy: yeah but it qualifies symbols

22:37 ,`(foo ~'foo)

22:37 clojurebot: (sandbox/foo foo)

22:37 technomancy: oh right; not paying attention here

22:38 DerGuteMoritz: no problemo

22:38 tensorpudding: it's just a reader macro

22:38 DerGuteMoritz: yes

22:38 but apparently it can't be used for a list of unqualified symbols

22:39 aha, perhaps thus hiccup's choice of keywords rather than symbols

22:39 I wondered about that the other day

22:43 kenth: why are there two quoting forms?

22:44 DerGuteMoritz: kenth: the ` form allows "unquoting", i.e. inside the quoted form you can switch back to evaluation

22:45 kenth: Conrad Barski has made a nice illustration of that: http://lisperati.com/backquote.jpg (except in clojure, unquoting is done using ~)

22:50 kenth: so ' does not allow unquoting?

22:50 DerGuteMoritz: that's right

22:55 amalloy: having ` qualify symbols is also hugely helpful in avoiding unintentional symbol capture in macros

22:56 but it's pretty rare you want to splice together a list *and* include literal symbols in it. if you just want to splice stuff together, you can write `(~@x ~y), which is the same as (concat x [y])

22:58 DerGuteMoritz: hm, indeed:

22:58 ,(let [x 'foo] `(~x))

22:58 clojurebot: (foo)

22:59 DerGuteMoritz: I assumed that literal symbols behave the same in this situation

23:00 err wait

23:00 jhirn: Is it wrong that I get the urge to write code instead of tests with Clojure? It feels illicit.

23:02 DerGuteMoritz: amalloy: the use case I have in mind is more like constructing a relatively complicated nested list structure with few unquotes, e.g. something like `(html (head (title ~title)) (body (h1 ~title) ~@body)

23:02 )

23:04 amalloy: yeah, hence keywords. clojure doesn't encourage the use of symbols as data when that data doesn't represent code you plan to execute, i think

23:04 DerGuteMoritz: yep

23:04 thus my enlightenment regarding hiccup above :-)

23:06 alas, something like ~@body in my example above is not possible with hiccup

23:06 but not terribly missing either

23:06 amalloy: sure it is

23:06 it's not clear to me what you're saying is not possible, but i'm confident it's possible

23:07 DerGuteMoritz: amalloy: splicing into a vector literal

23:08 you need to use concat, as you said earlier

23:08 amalloy: &(let [x [1 2 3]] `[foo ~@x])

23:08 lazybot: ⇒ [clojure.core/foo 1 2 3]

23:08 DerGuteMoritz: yeah then you have to take care not to have symbols in there :-)

23:08 amalloy: more importantly, in hiccup you don't have to splice at all. it ignores lists, so [:foo (list 1 2 3)] is the same as [:foo 1 2 3]

23:09 DerGuteMoritz: that's good

23:09 ok thanks for the feedback guys

23:09 gotta get some sleep now, hard to keep the eyes open

23:09 good night!

23:15 sandy1986: Hi, can anyone explain me how form validation in enlive works?

23:23 TimMc: sandy1986: I was not aware enlive had anything to do with that.

23:26 sandy1986: Mhh ... yeah

23:26 maybe I must use sandbar

23:28 emezeske: ,*clojure-version*

23:28 clojurebot: {:major 1, :minor 3, :incremental 0, :qualifier nil}

23:28 emezeske: &*clojure-version*

23:28 lazybot: ⇒ {:major 1, :minor 3, :incremental 0, :qualifier nil}

23:42 mbac: what's the most standard clojure csv parsing library?

23:48 ldh: how does one compare lists in clojure? (compare '(1 2) '(3 4)) throws an exception

23:51 nm, = does it :-|

Logging service provided by n01se.net