#clojure log - Jul 02 2012

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

0:00 xeqi: when there is a project.clj, yes

0:09 wingy: what is the recommended way to have something like rake

0:10 where i add a task and can run it eg. to git save my project on github

0:10 is it to add a task to lein?

0:10 if so, is it a plugin i should write?

0:14 uvtc: wingy, afaik, when you install a lein plug-in, it adds that plug-in's task into the list of tasks you seen when running `lein help`.

0:15 wingy: uvtc: yeah .. i wonder if adding a plugin is right thing to do if i wanna add eg. lein git save and it will commit and save my project to github

0:15 uvtc: wingy, Ah. Sorry --- dunno. I use git manually, myself.

0:16 What is proper github issue closing etiquette?

0:39 justdit: I use read-line in repl and it works, but when it comes to launching from file the program expects input forever though I enter a line several times

0:39 is there something specific that should be done to get it working?

0:45 wingy: how should i run my ring/compojure app in heroku?

0:45 what should be in Procfile?

0:46 justdit: wingy: there's the docs on heroku, but shortly web: lein run -m <path.to.file>

0:46 technomancy: wingy: this might help: https://devcenter.heroku.com/articles/clojure-web-application

0:48 wingy: hmm

0:49 in my file i have this line: (def app (handler/site main-routes))

0:49 and i run it with: lein ring server

0:49 in the heroku doc (and ring doc) they have:

0:49 (defn -main []

0:49 (let [port (Integer. (System/getenv "PORT"))]

0:49 (start port)))

0:49 and run it with: lein run -m <namespace>

0:50 i was following this guide: https://github.com/weavejester/compojure/wiki/Getting-Started

0:51 so the question is: should i follow the heroku guide or compojure guide and what is the diff between those "server start" lines?

0:52 akhudek: I prefer the heroku/ring way of starting the server

0:52 wingy: akhudek: from the compojure doc it says: This adds a bunch of commonly-used Ring middleware to your routes. Without this, you couldn't access cookies, or form parameters, or work with session variables.

0:53 ok ill make it simple and just follow the heroku/ring guide

0:53 akhudek: that's true, but you can easily wrap those things around your top level handler yourself

0:53 wingy: yeah

0:53 and know what is going on

0:53 akhudek: all lein-ring does is wrap your routes for you and starts a server in the same way as the heroku/ring doc is showing

0:54 wingy: right

0:54 akhudek: the only difference is that you have less control over things

0:54 wingy: yeah hate that

0:54 akhudek: also, for production use you are going to want to run either as a jar or a war file

0:55 not sure if lein-ring is compatible with either

0:55 wingy: ok i delete lein-ring and keep it simple .. no magic

0:55 that is ruby .. in clojure its called simplicity :)

0:56 technomancy: akhudek: nah, you can use `lein trampoline run` in production since heroku's build process freezes your dependencies, you don't need to generate a jar file.

0:58 akhudek: technomancy: I figured heroku might do something special (I don't know much about it), but was speaking for general use cases.

1:28 wingy: the -main function seems to be a fn to run from cli only using "lein run"?

1:28 that is, it shouldn't be used inside the program itself?

1:31 brehaut: you can use it from inside the program itself

1:31 its probably atypical to do so, but theres no real reason why you couldnt

1:32 adu: might be nice for a busybox clone

1:32 justdit: wingy: it's the same function as others, but can be interpreted as a launch point as it's say in C

1:42 wingy: justdit: this is because java is starting the main function as well?

1:43 kinda cool to have a default fn to launch .. i guess there is no need for me to have different tasks like in jake/rake/cake/make

1:44 i can just have them in -main fns and run them with: lein run -m <namespace>

1:44 hm .. or perhaps its still better to have it as a lein plugin i think

1:45 so others can reuse

1:56 is there a better way to write this: (if (System/getenv "PORT") (System/getenv "PORT") nil)

1:57 keeping it DRY

1:58 xumingmingv: (if-let [xxx (System/getenv "PORT")] xxx nil)

2:00 amalloy: uh, unless System/getenv returns false, you can just write (System/getenv port)

2:01 and xumingmingv, that's just a long way to write ##(doc or)

2:01 lazybot: ⇒ "Macro ([] [x] [x & next]); Evaluates exprs one at a time, from left to right. If a form returns a logical true value, or returns that value and doesn't evaluate any of the other expressions, otherwise it returns the value of the last expression. (or) returns nil."

2:01 xumingmingv: amalloy, ah yes...

2:02 Sindikat: hello everyone! in Clojure arrow macro allows to convert (f1 (f2 (f3 x))) to (-> x f1 f2 f3). but what if one of the function requires multiple arguments? how to convert the sexp (f1 "a" (f2 (f3 x)))?

2:03 amalloy: (->> x (f3) (f2) (f1 "a"))

2:03 Sindikat: amalloy: what if these required args go after x like in (f1 (f2 (f3 x)) "a")?

2:03 amalloy: and the ordering in your premise is backwards

2:03 Sindikat: amalloy: oh yeah, my bad

2:04 amalloy: (-> x (f3) (f2) (f1 "a"))

2:17 cljs_newb_0245: it has been said: if you are not doing most of your clojurescript devel in a repl, then you are doing it wrong

2:17 I ahve built web apps on top of cljs

2:17 i still do not know how to use the cljs repl

2:17 is tehre a way to use the cljs repl w/o using clojurescript one?

2:17 I like my cljs/clojure webstack using ring/compojre

2:17 and I dont' want to use clojurescriptone

2:36 justdit: how can I make optional arguments of the function not to nest in each function? here the code http://pastebin.com/6nfa9XyJ

2:38 wei_: is there a multiple-binding version of if-let? e.g. (if-let [a (could-be-nil) b (could-also-be-nil a) (do-something))

2:39 jhowarth: How can I get paredit to work for cljs files?

2:40 Nevermind I figured it out, thanks.

2:40 adu: justdit: apply

2:41 justdit: also, & isn't optional arguments, it's rest arguments

2:41 justdit: adu: ok, but what about if there's also required args?

2:41 adu: apply should work

2:41 (defn f [a b & rest] …)

2:42 (f a b c d) is the same as (apply f a b '(c d))

2:43 justdit: adu: thanks

2:43 adu: justdit: oops vector

2:44 I'm too used to scheme

2:44 justdit: haha :)

2:44 adu: (apply f a b [c d])

3:59 michaelr525: good morning

3:59 !

4:27 SrPx: What does ~@something stands for

4:29 clgv: SrPx: unquote splicing - it inserts element from something as enumeration in the code

4:29 SrPx: hm? like (foo ~@'(a b c)) = (foo a b c) ?

4:30 clgv: example: `(hash-map ~@[:a 1 :b 2]) will return (hash-map :a 1 :b 2)

4:30 hyPiRion: SrPx: yes.

4:30 SrPx: okay, thanks.

4:31 clgv: &`(hash-map ~@[:a 1 :b 2])

4:31 lazybot: ⇒ (clojure.core/hash-map :a 1 :b 2)

4:31 clgv: &`(hash-map ~[:a 1 :b 2])

4:31 lazybot: ⇒ (clojure.core/hash-map [:a 1 :b 2])

4:31 SrPx: Also I'm on lein repl, just modified core.clj, and called (require 'mystuff.core) followed by (mystuff.core/main) but it displayed the old main. any idea why

4:31 clgv: SrPx: I think there is a :reload option

4:33 hyPiRion: SrPx: If you use Emacs, this one is good for customizing Emacs for Clojure: https://github.com/ftravers/PublicDocumentation/blob/master/clojure-development-setup.md

4:33 clgv: I have a question as well: from an inserted println I see that a namespace is loaded twice. there is a deftype in the namespace which is defined twice as well, so that I get a ClassCastException - how can that happen? how can I fix it?

4:33 hyPiRion: Also solves the issue you currently got.

4:35 SrPx: hyPiRion: hm

4:35 hyPiRion: SrPx: Though I know there's some way of doing it without Emacs, but I'm not sure how to do it. I'd think it's possible to google it.

4:39 SrPx: hyPiRion: I wish I was aware of this before

4:39 I've already spent a day trying to get emacs to work so I'm not coming back to that now

4:39 );

4:39 but thanks

4:41 hyPiRion: SrPx: Ah, I know the feeling.

4:42 SrPx: hyPiRion: =(

4:43 hyPiRion: SrPx: Okay, so if you do (require :reload-all 'mystuff.core) you should reload the code.

4:44 SrPx: hyPiRion: thanks!

4:45 on emacs this is automatic everytime you edit?

4:46 hyPiRion: also do I have to type (whatever.core/myfunc) everytime? );

4:46 hyPiRion: SrPx: No, you have to do Control-c Control-k

4:46 SrPx: oh

4:47 hyPiRion: SrPx: You can use 'use' instead, which gives you the possibility to do (myfunc ...) directly.

4:47 e.g. (use 'whatever.core)

4:47 SrPx: thaanks hyPiRion

4:47 hyPiRion: You're welcome. :)

4:52 ro_st: technomancy: help, please! i've just put all this into ~/.lein/profiles https://www.refheap.com/paste/3411

4:53 i've run lein2 deps, and restarted my swank repl with clojure-jack-in

4:53 but now i'm not getting warn-on-reflection errors and i'm not able to use ring-serve either. does the emacs repl stuff use .lein/profiles.clj?

4:54 i've confirmed that those props are set in the output of lein2 pprint

5:21 AWizzArd: Btw, deutschsprachige Clojure-Nutzer sind auch nach #Clojure.de eingeladen. Btw, german speaking clojure users are also invited to #Clojure.de

5:49 ro_st: anyone using ring-serve figured the 'org.mortbay.log.Logger classnotfound exception' issue out?

5:52 stain: hi

5:53 I have an int that seems to turn into a long on every second time I run a test

5:53 is this expected, and should I be able to force it somehow?

5:57 ro_st: how do i ensure that org.mortbay.log.Logger is available to my clojure program?

7:05 fbru02: hi all , anoyone has used classes in clojure from a mvn project in eclipse ?

8:15 hyPiRion: fbru02: If you use Leiningen as a project manager, you can add dependencies from the maven repository without much/any work.

8:16 fbru02: hyPiRion: hi , thanks ! I want to add clojure to an existing mvn/eclipse project.... it builds ok with mvn command line but eclipse doesn't find out about the new classes that are using gen-class

8:16 any ideas ?

8:17 hyPiRion: fbru02: Ah, so you want it the other way around. I'm afraid I'm of little help there, I've not used Maven at all.

8:17 fbru02: thanks anyway !

8:18 hyPiRion: However, I'm pretty sure there should be some tutorials or something if you google enough. Clojure itself uses maven, so there should be compability.

8:43 nDuff: fbru02: Can't help you with the "in Eclipse" part, but otherwise, yes.

8:43 fbru02: which Maven plugin for Clojure are you using?

8:45 fbru02: nDuff: com.theorinpractice.clojure-maven-plugin:1.3.10

8:46 stain: my g.. this is f..d up, the longs turn into ints and the ints into longs, and nothing is correct

8:46 fbru02: nDuff: question though : should I name my files like util.clj and the ns should be sth like (ns com.company.Util)

8:46 nDuff: fbru02: ...so, the more actively maintained one is probably org.cloudhoist.plugin.zi, though I personally have had some issues with it.

8:46 fbru02: ?

8:47 nDuff: fbru02: I personally stick with all-lower-case in both places.

8:48 stain: I've not really seen camel case namespaces much in either Java nor clojure

8:48 fbru02: nDuff: thanks and then in java sth like : util myUtil = new util();

8:48 ?

8:49 stain: oh, this is to make Java classes in the end?

8:49 fbru02: stain: yes i need to call clj from java

8:52 stain: if the (implied) class is meant to be used by Java, then should you not rather use reify, gen-class or proxy?

8:52 fbru02: stain: i'm using gen-class, soryy i left that bit of info out

8:52 hugod: nDuff: what issues have you had with zi?

8:55 mystiiq: hey, has anyone lately used this library: https://github.com/ugglan/cljaws

8:58 stain: fbru02: oh, then I guess CamelCase is the cleanest. Just avoid having a noncamelcased duplicate, as it would fall apart in Windows.

8:58 mystiiq: I cloned that repo, ran repl and tried to go through those samples on that README but I get this error: Can't dynamically bind non-dynamic var: cljaws.core/*aws-id*

8:59 stain: mystiiq: that should just be a warning

9:01 mystiiq: using Clojure 1.1.. due for a fork?

9:02 mystiiq: I'm using 1.4 because it cant find 1.1 from the repos

9:02 nDuff: hugod: Unable to find the mojo 'compile' (or one of its required components) in the plugin 'org.cloudhoist.plugin:zi' Could not locate clojure/plexus/compiler/impl__init.class or clojure/plexus/compiler/impl.clj on classpath:

9:06 hugod: https://gist.github.com/2dd7f8243fed14e2ab25 has the full thing (including a classpath dump)

9:07 hugod: nDuff: anything particular (zi related) in you pom?

9:09 nDuff: hugod: Added a pom.xml fragment to the gist.

9:14 ...odd, since clojure/plexus/compiler/impl.clj is there in clojure-maven-plexus-compiler-0.3.2.jar, which is present in the classpath dump...

9:16 bordatoue: hello guys, just wondering how to interpret clojure doc for example when it says (writer x & opts) how do I find out what the opts are ?

9:17 hello

9:18 why is that there is no response

9:18 kmicu: small community in Europe

9:18 bordatoue: back from weekends

9:19 kmicu: give a link to that doc

9:20 bordatoue: kmicu http://clojuredocs.org/clojure_core/clojure.java.io/writer

9:22 kmicu: even if i print the documentation using ;(doc clojure.java.io/writer)

9:23 how do i know what the supported options are ? please

9:24 kmicu: http://clojure.github.com/clojure/clojure.java.io-api.html#clojure.java.io/writer

9:25 nDuff: can you please help me with my query

9:25 kmicu: bordatoue: this is only wrapper for http://docs.oracle.com/javase/1.5.0/docs/api/java/io/Writer.html

9:26 cmiles74: bordatoue: This was a hard one, the options are part of the protocol for the writer. The documentation is on the protocol, under IOFactory. http://clojure.github.com/clojure/clojure.java.io-api.html

9:26 kmicu: the same options apply

9:27 bordatoue: kmicu: okay, so is there any identification tag used to indicate a wrapper

9:27 cmiles74: thanks

9:27 cmiles74: I think kmicu beat me to it. :P

9:28 bordatoue: kmicu: many thanks, is there any way to distinguish between a wrapper

9:28 kmicu: bordatoue: (defn ^Writer writer

9:28 ^Writer is a type

9:28 bordatoue: kmicu: so that mean i need to search the source ,

9:29 kmicu: only for this java interop methods

9:29 bordatoue: kmicu: thanks anyway, i think i got the gist of it

9:32 kmicu: bordatoue: it is better if you explain what is your goal ;)

9:36 bordatoue: kmicu: goal is to comprehend clojure doc without any ambiguities

9:46 dnolen: bordatoue: looks like the docs for opts are lacking. submit a doc patch.

9:56 hugod: nDuff: I should have time to try and repro a little later - I'm wondering if it is related to clojure 1.4 vs 1.3

9:59 nDuff: hugod: Seems possible -- there was a bug in the 1.3.x line which pushed me to 1.4 early.

10:08 mystiiq: how can I use classpath and library path at the same time?

10:26 Scorchin: Are there any decent Clojure Spidering libs, or basic "link checkers" that you know of?

10:45 mystiiq: what could this mean: Exception in thread "main" java.lang.IllegalArgumentException: No matching method found: getOrCreateBucket for class clojure.lang.Var$Unbound

10:46 tbaldridge: mystiiq: context? It looks like you're trying to use a deffe'd var that's never been given a value

10:46 *def'ed

10:47 Something like (do (def foo) (.getOrCreateBucket foo))

10:47 mystiiq: I'm trying to use https://github.com/ugglan/cljaws library and I just followed the examples in the README, I am using clojure 1.4.0 though

10:48 kmicu: Scorchin: https://github.com/michaelklishin/crawlista ?

10:49 Scorchin: kmicu: thanks, I'll check it out

10:49 nDuff: mystiiq: Presumably that var is expected to be bound to something.

10:49 mystiiq: tbaldridge: here should be the problem somewhere: https://github.com/ugglan/cljaws/blob/master/src/cljaws/s3.clj#L30

10:49 nDuff: mystiiq: If the examples show wrapping your calls within something else that sets up context, that would explain it.

10:50 tbaldridge: yeah, it looks like you might be missing the with-s3 macro?

10:52 mystiiq: okay, I got it working, yeah I forgot to restore it to (with-aws :s3 ...)

11:29 edoloughlin: Anyone have any idea why 'lein ring server' isn't calling the specified :ring/:handler? https://gist.github.com/3033784

11:31 foxdonut: edoloughlin: that should point to api instead of boot

11:35 edoloughlin: foxdonut: oh, thanks.

11:36 foxdonut: welcome

11:39 edoloughlin: One thing: I do config/init and websockets/init to init my DB and websockets in 'boot'. Where should I do these?

11:40 Also: how do I specify a port other than 3000?

11:41 Am I just running up against the lein ring convention - should I stop using it and just run as a normal app?

11:44 duck1123: edoloughlin: That's part of the reason I've stayed away from that plugin. Couldn't figure out how to do the init correctly

11:44 edoloughlin: Ok. I'm not being stupid/lazy then...

11:45 duck1123: well, at the very least, you're not the only one being stupid/lazy

11:46 I wonder if you could use decorate to wrap a fn that's only called once on startup to hook in your init? (not sure that's a good idea)

11:48 TimMc: Raynes: RefHeap broken? A paste URL I posted the other day now has something different...

11:49 edoloughlin: duck1123: I'm using a defonce in another part of my app to initialise email templates, which is definitely stupid AND lazy.

11:50 * nDuff is actually thinking of doing something very similar -- he has templates specified as resources, but that makes them hard to update from the REPL.

11:51 duck1123: In Ciste, I have definitializer, which allows you to specify code to be evaluated as soon as the config system is ready

11:51 TimMc: Raynes: I think the ID was re-used for a new paste.

11:53 foxdonut: edoloughlin: for different port you can just do "lein ring server 8080"

11:54 acheng: hi all. quick clojure.repl/source question: it "requires that the symbol resolve to a Var defined in a namespace for which the .clj is in the classpath." my classpath includes directory src/ ... i have src/foo/bar.clj with namespace foo.bar where baz is def'd and has a docstring. (doc baz) shows the docstring. but (source baz) and (source foo.bar/baz) both say "Source not found". what should i do differently?

11:55 S11001001: acheng: what's (meta #'foo.bar/baz)

11:55 edoloughlin: foxdonut: thanks. I didn't think to look beyond 'lein ring help' (it's not mentioned there)

11:55 S11001001: ,(meta #'into)

11:55 clojurebot: {:ns #<Namespace clojure.core>, :name into, :arglists ([to from]), :added "1.0", :static true, ...}

11:56 S11001001: ,(drop 5 (meta #'into))

11:56 clojurebot: ([:doc "Returns a new coll consisting of to-coll with all of the items of\n from-coll conjoined."] [:line 6026] [:file "clojure/core.clj"])

11:56 acheng: S11001001: it shows namespace name doc line and file

11:56 foxdonut: edoloughlin: for init just define a no-arg function and specify it in :init next to :handler

11:56 S11001001: are you using slime?

11:56 acheng: i think so :)

11:56 edoloughlin: foxdonut: Ok. Thanks.

11:57 acheng: M-x clojure-jack-in

11:57 S11001001: acheng: stick point on symbol, press M-.

11:57 acheng: S11001001: takes me to the definition in the source code

11:58 duck1123: acheng: try doing C-c C-k in that file to make sure it's loaded properly

11:58 foxdonut: edoloughlin: you're welcome. you (and duck1123) might want to look at https://github.com/weavejester/lein-ring/ before you just write it off :-)

11:58 S11001001: is that more or less useful than c.r/source?

11:59 acheng: S11001001: that's pretty good. the user would have to go back to the repl if that's where he wanted to be. duck1123: after compiling still says source not found.

11:59 duck1123: foxdonut: the other reason I've written it off is because I use Aleph

12:00 S11001001: acheng: seems that savings from not typing out source call more than balances out

12:00 acheng: S11001001: you're right

12:00 S11001001: you also get context of surrounding comments &c

12:01 duck1123: acheng: ok. I don't use the source macro much, I just know that if I don't send code via C-c C-k then I lose acurate line numbers

12:01 acheng: S11001001: still bothers me a little that it doesn't yet work for me

12:01 S11001001: like i'm driving my old vw golf again

12:02 S11001001: I would rather liken it to wondering where the stick is in an automatic

12:03 acheng: S11001001: ah yeah. "how do i do that thing that takes more work?"

12:03 foxdonut: duck1123: fair enough, if you found a solution that suits your needs..

12:04 acheng: S11001001: i hadn't realized that M-. worked at the repl and not only in a source buffer. nice.

12:22 clgv: what's the shortest approach to find out whether a given symbol occurs in a nested form?

12:24 technomancy: clgv: that could be the first legitimate use of flatten I've seen

12:25 clgv: technomancy: flatten + some?

12:25 technomancy: right

12:25 I almost said flatten+member; what is up with my brain this morning?

12:25 gfredericks: don't you mean create an atom and then use clojure.walk?

12:26 technomancy: =P

12:26 gfredericks: I've literally seen that done. Otherwise I doubt I could have thought of it.

12:27 clgv: technomancy: though I am not sure if I have to check nested map literals as well. but thats very unlikely

12:28 technomancy: clgv: you could use tree-seq if you need to be picky

12:29 clgv: well the forms have to be some kind of calculations from integer to integer - so there shouldnt be maps

12:52 identical? checks only for object reference equality, right?

12:52 dnolen: clgv: yes

12:54 clgv: thx

12:54 S11001001: ,({1 2, 2 3, 3 42} 3) ; clgv :)

12:54 clojurebot: 42

12:55 clgv: S11001001: erm, what?

12:55 S11001001: is partial function from integer to integer

12:57 clgv: S11001001: what do you want to tell me with that?

12:57 my search question is solved by `(not-any? #{sym} (flatten expr))`

13:09 TimMc: &(`[~@`#()](+))

13:09 lazybot: ⇒ fn*

13:10 progo: didn't know K was supported here :o

13:12 * foxdonut is utterly lost.

13:12 technomancy: you are in the #clojure channel on irc.freenode.net

13:12 cshell: thanks!

13:12 technomancy: exits are to the north and east.

13:12 foxdonut: LOL

13:12 technomancy: (you are likely to be eaten by a grue?)

13:13 foxdonut: ,'(pick up wallet)

13:13 clojurebot: (pick up wallet)

13:13 foxdonut: ,'(go north)

13:13 clojurebot: (go north)

13:13 llasram: You see here a set of matched braces and a lambda symbol (providing light)

13:13 wkelly: haha

13:14 foxdonut: the last exchange between S11001001 and clgv lost me, then TimMc added the utterly.

13:16 clgv: foxdonut: I didn't get what S11001001 wanted to tell me either

13:18 foxdonut: S11001001 is now known as S201

13:19 llasram: foxdonut: TimMc's comment makes more sense once you realize that also:

13:19 &(`[~@`#()](*))

13:19 &(`[~@`#()](*))

13:19 lazybot: ⇒ []

13:21 * clgv fears the arrival of the perl hackers.

13:21 clgv: ;)

13:23 foxdonut: llasram: that made my brain hurt, but I get it now :) thx

13:24 TimMc: foxdonut: Reopening an old experiment in writing Clojure without alphanumeric characters.

13:25 This will not go far without getting resolve or str.

13:25 foxdonut: TimMc: once of those obfuscated code exercises? or like writing a story without using the letter e?

13:25 *one of those

13:26 TimMc: THe latter. Obfuscation is simply a byproduct.

13:27 foxdonut: interesting.

13:28 technomancy: that reference to a text adventure game was a hoot!

13:29 * TimMc fires up ADVENT

13:30 TimMc: 19:15 < gfrlog> all we have is ints, booleans, ratios, and infinite recursion

13:32 Oh, here we are: http://clojure-log.n01se.net/date/2011-04-06.html#19:04

13:32 foxdonut: TimMc: how about never using if?

13:33 TimMc: Ideally we'd get eval, then defmacro...

13:33 foxdonut: http://www.antiifcampaign.com/

13:34 TimMc: Oh, I see.

13:48 &(`[~@'`[]](+)) ;; I can get interesting symbols, but not their vars

13:48 lazybot: ⇒ clojure.core/apply

13:57 gfredericks: TimMc: I said that up there?

13:57 TimMc: gfredericks: Yep! It was funny to look through the conversation and realize how much I'd forgotten of what I had figured out.

13:58 gfredericks: TimMc: what on earth was I talking about?

13:58 wait I just googled it

13:59 that is such a weird ability

13:59 oh that was a fun conversation

14:00 TimMc: If only ~'clojure.core/apply was a valid way to resolve a symbol...

14:00 gfredericks: &`@+

14:00 lazybot: ⇒ (clojure.core/deref clojure.core/+)

14:01 gfredericks: okay back to work. Was just weirded out to see the word 'gfrlog'

14:01 TimMc: Except it's a symbol, not a var. :-)

14:03 gfredericks: ,'[<TimMc> Except it's a symbol, not a var. :-)]

14:03 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: Unmatched delimiter: )>

14:04 gfredericks: aw crap

14:04 it was almost readable

14:12 ,1 2 3

14:12 clojurebot: 1

14:12 gfredericks: ,1 2 3)

14:12 clojurebot: 1

14:12 TimMc: &5 Yep, all this is ignored.

14:12 lazybot: ⇒ 5

14:12 gfredericks: &1 2 3)

14:12 lazybot: ⇒ 1

14:13 TimMc: &(read "1 2 3")

14:13 lazybot: java.lang.ClassCastException: java.lang.String cannot be cast to java.io.PushbackReader

14:13 TimMc: &(read-string "1 2 3")

14:13 lazybot: ⇒ 1

14:13 gfredericks: yeah

14:19 goodieboy: has anyone used the amazon dynamodb client, "rotary"? https://github.com/weavejester/rotary

14:19 I'm attempting to create a table, but only get a null pointer exception

14:24 baoist: How would one go about dealing with optional arguments and recursion? (e.g.) I would be getting [& args] to be (a b c) ((b c)) (((c))) when I use (rest args)

14:26 TimMc: The issue being that 'apply can't be used with 'recur?

14:27 baoist: TimMc: No, I just use (foo a b c) and with every recursion it will put it in another list

14:27 TimMc: Oh, you're not using recur? Then (apply foo ...)

14:28 That will unwrap the restargs before sending them in.

14:28 baoist: TimMc: oh, gotcha.

14:28 Thanks

14:28 TimMc: baoist: Oh, and I was wrong... recur plays well with restargs after all.

14:29 &((fn f [c & args] (if (seq args) (recur (inc c) (rest args)) c)) 0 'a 'b 'c)

14:29 lazybot: ⇒ 3

14:29 baoist: well yeah, I do that, but after the first run-through it's no longer b and c, it's (b c)

14:31 so I would call (foo a b c), and it will just continue to put it in another list, by the end it would be ((( c ))). If it would let me get that far without throwing an error

14:31 TimMc: baoist: Right, (apply foo ...)

14:31 baoist: okay, great.

14:31 thanks much :D

14:32 TimMc: baoist: And you can't just use recur here?

14:32 You're not recursing from the tail position?

14:32 baoist: I am

14:32 but it continues to wrap (rest args) in another list with every recur run

14:33 TimMc: &((fn f [accum & args] (if (seq args) (recur (conj accum args) (rest args)) accum)) [] 'a 'b 'c) ;; works for me...

14:33 lazybot: ⇒ [(a b c) (b c) (c)]

14:39 baoist: huh, interesting. I must be doing something terribly not right. I'll look into this

14:45 wingy: cool that you can connect through the repl to your app's env

14:46 this didn't seem possible on node.js

14:46 and manipulate your app on the fly

14:47 dnolen_: wingy: it's possible tho not as natural since Node.js code tends to be wrapped in closures to avoid collisions in the global context.

14:49 wingy: i c

15:17 antares_: Raynes: hey

15:21 Cheiron: Hi, would you please have a look at http://pastie.org/4188934 ?

15:21 Raynes: antares_: ?

15:22 Cheiron: any idiomatic way to achieve that?

15:23 I can embed a let form inside for form, but it is idiomatic?

15:24 antares_: Cheiron: for has the :let key, also there is nothing wrong with using let inside for

15:24 Raynes: how do you like monger?

15:25 Raynes: I fixed all the issues I could find that are in Clojure. The JS ones will take more time.

15:25 Cheiron: antares_: I'm waiting for fortecass :) (hope I spelled it right)

15:25 antares_: cassaforte?

15:26 Raynes: antares_: I found an issue last night that I haven't fixed yet.

15:26 fenton: ðð

15:26 antares_: yeah, it is very close to having most useful features but somehow prepared statements do not work with cassandra 1.1 :(

15:26 Cheiron: yes, cassaforte. sorry :)

15:26 Raynes: antares_: Try creating two private pastes. They'll both have the same id, which is also your user id. Somewhere ids are getting mixed up, but I'm not sure where.

15:26 You don't have to fix that though. I'll get to it soon.

15:26 antares_: as soon as I figure out why, it will be trivial to add all the key operations on top of CQL and prepared statements

15:27 Cheiron: cassandra 1.1.2 is just out of the oven

15:27 antares_: Raynes: well, there are like 3 ids in a document, I wasn't sure which one is for what

15:27 Cheiron: I tried master for like 3 hours on Saturday. I guess I need to read the source to understand what I may be doing wrong. Cassandra complains about ?s in the query :/

15:28 the ticket for prepared statements was closed in December last year

15:28 Cheiron: antares_: regarding the :let modifier. I have to place it after all the binding i did in for form?

15:29 Raynes: antares_: The user id should have been called 'user'.

15:29 At least, that's usually how I did it I think.

15:29 paste-id, IIRC, is the id you see in the URL when you visit a paste. If it is a number, then it is the same as 'id'.

15:30 antares_: Raynes: ok

15:35 Cheiron: see the 3rd example here: http://clojuredocs.org/clojure_core/clojure.core/for

15:41 Cheiron: thank you

15:44 arohner: does anyone have experience w/ JGroups?

15:44 i.e. would you recommend it for clojure + ec2?

16:06 mindbender: technomancy: it seems clojure-jack-in can't locate the swank specific slime and slime-repl that's why I'm getting void-function for slime-output-buffer

16:09 zerokarmaleft: mindbender: what version of swank-clojure do you have installed?

16:13 mindbender: zerokarmaleft: I'm using lein2 so I added lein-swank 1.4.0 to profiles.clj

16:14 zerokarmaleft: mindbender: update to 1.4.4, that sounds similar to a problem i had a couple weeks ago

16:15 foxdonut: wow, if you go on amazon, select books and search for "closure", it actually says "Did you mean: clojure"

16:16 pisketti_: :D

16:20 pipeline: foxdonut: i called a bookstore and had a long conversation on that subject

16:20 "yes the author had a sense of humor"

16:22 technomancy: unlike google who take common terms and don't even change the spelling

16:34 duck11231: What do you mean you can't find relevant content for "go"

16:42 foxdonut: pipeline: the author of what?

16:43 pipeline: foxdonut: the clojure language

16:44 mindbender: zerokarmaleft: thanks 1.4.4 got me near, but now I have cygwin interferring with byte compilation by inserting stuff into path to compile, I suppose you are not using cygwin.

16:45 zerokarmaleft: mindbender: sorry no, i'm not

16:45 qubit[01]: is VirtualBox an option for you mindbender ?

16:45 ForSpareParts: I asked this in here once quite a while ago, but: do any of you know of a way (probably a macro?) to do an "inline let" with an imperative-style syntax? Like: http://pastebin.com/Ei5Lhv72

16:45 mindbender: not really

16:46 ForSpareParts: Obviously, it would still be invalid to redefine a in that example after you give it a value -- I'm not trying to break functional programming, just tweak syntax.

16:47 mindbender: zerokarmaleft: I have run clojure-jack-in successfully on Ubuntu. i'm using windows for now to work

16:47 tbaldridge: mindbender: I'm sorry

16:47 brehaut: ForSpareParts: just use a let; for side effecting only stuff, just use _ as the LHS of the binding pair. ugly things should be ugly

16:48 mindbender: tbaldridge: thaks

16:48 err: thanks

16:48 acheng: ForSpareParts: i do the same as brehaut for web tests that have many steps that change the browser

16:49 foxdonut: pipeline: so you were talking to the bookstore person about the spelling of "clojure" ?

16:49 ForSpareParts: brehaut, Wasn't really thinking of side-effect only stuff. Rather, I was imagining scenarios where it only really makes sense for something to have scope starting in the middle of the function -- let seems sort of over-the-top ugly, for that.

16:50 Would that really be such bad practice?

16:50 brehaut: what do you mean 'has scope starting in the middle of the function'?

16:50 pipeline: foxdonut: yes

16:51 amalloy: ForSpareParts: no offense, but that's a bit ridiculous. let is for introducing scopes; it's not ugly or over the top. if you want some new variables in scope, use a let

16:52 ForSpareParts: brehaut, I guess I probably mean "the standard use case for a let" -- I'm not trying to start a fight or anything, I just think it's easier to read and edit my code when I'm not starting new blocks all the time. Maybe I'm not writing my functions properly?

16:53 foxdonut: pipeline: that's funny

16:53 brehaut: ForSpareParts: i am guessing that you are doing something funny then.

16:53 amalloy: having new blocks all the time is a visual hallmark of the functional style

16:54 it helps if you stop thinking of them as "blocks", because there's no such thing as statements and blocks of statements; just expressions nested inside expressions

16:54 foxdonut: hear here amalloy

16:54 brehaut: ForSpareParts: without actually seeing some of your code, i could say for sure, but it sounds like if you are creating lots of functions with many lets inside them that you are doing something unussual.

16:54 ForSpareParts: amalloy, That makes sense. I'm just thinking about how convenient it was to have the <- syntax in Haskell's do blocks. It made for nice, simple shorthand.

16:56 amalloy: well, that's fair enough. haskell flattens out your monadic code; clojure flattens out some of your lets and list-comprehensions

16:56 brehaut: ForSpareParts: using do inplace of a let in haskell is extraordinarily ugly too

16:57 ForSpareParts: amalloy, Would it be terribly... un-Clojurey to try to have both?

16:57 foxdonut: the do blocks in haskell made me the feel the same way about veggie hot dogs; why go all pure and against procedural code only to end up with something that looks exactly like it?

16:57 brehaut: foxdonut: because sometime you have to write procedural code?

16:58 foxdonut: brehaut: you're right. I just like clojure's approach better.

16:58 amalloy: ForSpareParts: have you read On Lisp?

16:59 i'm assuming not; there's a relevant excerpt at https://gist.github.com/ec2f11312dbae9f26224

16:59 ForSpareParts: foxdonut, I only used Haskell a little bit, for a class, but I found that sometimes it was just easier to *think* about alogrithms if I broke them down into steps. Even if I'm not writing crazy, state-mutating code, it helps to be able to think "first this, then that, then the other thing"

16:59 amalloy, I have not. I'll look at that.

17:01 brehaut: ForSpareParts: are you tending to write long functions or short functions in most of your code?

17:01 foxdonut: ForSpareParts: I agree, for the "first this then that" part I like to use ->

17:01 but the pieces in the chain after -> are all functions.. similar to | on the command line

17:02 ForSpareParts: brehaut, They feel long to me, in Clojure code. But I don't know how they'd stack up (and I don't have any samples handy)

17:03 foxdonut, Hm. That looks interesting, I haven't seen it before (super noob, here). Not what I'm used to exactly, but it might do...

17:04 foxdonut: ForSpareParts: you might like it. it's like (<other> (<then> (<first> x))) but instead is (-> x first then other)

17:05 ForSpareParts: foxdonut, Definitely cool. What if I'm looking to reuse old results, though? Like if I calculate a number and then want to add it to two separate values for different purposes?

17:06 gtrak: is there a simple shortcut for seqofvectors->csv?

17:06 amalloy: use a let, dude

17:06 brehaut: ForSpareParts: let ;)

17:06 foxdonut: what they said :)

17:07 hyPiRion: gtrak: you mean like ##(clojure.string/join ";" [1 2 3])

17:07 lazybot: ⇒ "1;2;3"

17:07 gtrak: suppose so

17:07 just wonder if anyone's done it before I reinvent it :-)

17:07 foxdonut: (let [tuce tomates n mayo] (Double. "cheeseburger"))

17:08 TimMc: :-D

17:08 gfredericks: Any thoughts on how to do "if" in alphanumerics-less Clojure?

17:09 gfredericks: Or really, any lazy evaluation?

17:11 uvtc: cemerick, in the Clojure Programming book, p 147 (maze example, `maze` function --- btw, a real mind-bender, thank you!), was there any reason `when-let` was used instead of `if-let`?

17:11 My understanding is that you would only use when-let if you wanted an implicit `do`.

17:15 cemerick: uvtc: when is equivalent to an if with no then form. If the condition isn't logically true, then nil is returned. Using when (or when-let in this case) is an explicit hint to the reader (of any code) that nil is the value of the form when the conditional isn't logically true.

17:16 TimMc: ,(#(% [% (+ (*)(*)(*)(*)(*))]) #(if (= (% (*)) (+)) (*) (* ((% (+)) [(% (+)) (- (% (*)) (*))]) (% (*)))))

17:16 clojurebot: 120

17:16 technomancy: uvtc: it's a hotly-contested controversy, but you are correct.

17:16 cemerick: Otherwise, you have (if condition (foo)), which would make a careful reader wonder if someone just forgot the 'then' form.

17:17 technomancy: cemerick: you're arguing that making `if`'s third argument optional was a design mistake?

17:18 uvtc: cemerick, Thanks!

17:18 TimMc: &(#(%[%(+(*)(*)(*)(*)(*)(*)(*))])#(if(=(%(*))(+))(*)(*((%(+))[(%(+))(-(%(*))(*))])(%(*)))))

17:18 lazybot: ⇒ 5040

17:18 cemerick: technomancy: I'd say so, yeah.

17:18 TimMc: So close! Just need to get rid of that "if".

17:18 gfredericks: TimMc: why do you need ifs to generate numbers?

17:18 technomancy: that's ... interesting

17:18 TimMc: Well, I wanted to write facetorial, you see.

17:19 factorial, even

17:19 uvtc: (seems like the doc for `when-let` should mention (1) that there's an implicit `do`, and (2) that it evaluates to nil when the thing you're binding is falsey.

17:19 cemerick: ,(doc when-let)

17:19 clojurebot: "([bindings & body]); bindings => binding-form test When test is true, evaluates body with binding-form bound to the value of test"

17:19 hyPiRion: TimMc: Is that a y-combinator in disguise?

17:19 gfredericks: TimMc: oh, I just saw your question

17:19 technomancy: uvtc: I'd argue that relying on the return value of when or when-let is a mistake

17:19 gfredericks: TimMc: one thing I know is that if can be emulated with a map

17:20 cemerick: technomancy: are they going to return 42 or something?

17:20 gfredericks: TimMc: or a vector!

17:20 TimMc: hyPiRion: Maaaaybe. :-)

17:20 gfredericks: No good, lookups are eager.

17:20 gfredericks: TimMc: wat?

17:20 technomancy: well, not a mistake, but a smell

17:20 uvtc: technomancy, inneresting food for thought. Thanks.

17:20 TimMc: Well, it's a recursive function, innit?

17:20 cemerick: "If else is not supplied it defaults to nil." — http://clojure.org/special_forms#if *shrug*

17:20 gfredericks: TimMc: if you can make your conditional return 0 or 1, you can emulate an if

17:21 TimMc: I remain unconvinced. You're going to get a stack overflow that way.

17:21 https://gist.github.com/3035760 for the expanded code, btw.

17:22 technomancy: uvtc: IMO it's crazy for seeing a 2-arg if to make you wonder if the author forgot a clause

17:22 gfredericks: TimMc: can the conditional be transformed to return 0/1?

17:23 amalloy: technomancy: when i see a 2-arg if i wonder if the author forgot a clause or just hates me. but i'm aware that there are people who feel the same way about seeing a single-expression when-body

17:23 cemerick: I've always considered it good form to put an else form in other languages with a comment like "left intentionally empty" if it is so.

17:23 TimMc: gfredericks: Sure, but it's gonna be bad.

17:24 gfredericks: TimMc: so then replace #(if foo bar baz) with #([#(bar) #(baz)] numeric-foo)

17:24 TimMc: I'll use a map.

17:24 gfredericks: o_O?

17:24 clojurebot: reverse psychology is even less rigorous than forward psychology

17:24 cemerick: *Actually*, there was a bug in nREPL that trptcolin caught where I had written (if conditional then), but was missing the else. :-P

17:25 TimMc: gfredericks: THe args to the lookup are going to be evaluated first, meaning BOOM stack overflow.

17:25 If I could get a lazy seq...

17:26 (if (= a b) c d) can be written ({a c} b d), but only for non-recursive c and d.

17:27 amalloy: TimMc: i think you're missing gfredericks's point. just use closures to get laziness

17:27 technomancy: cemerick: ok, but for that to be your first thought when you see it would only make sense if there was consensus on the topic

17:27 TimMc: amalloy: Oh! Thanks.

17:27 gfredericks: okay so I'm not crazy?

17:27 TimMc: Still trouble, since I can't nest #().

17:27 gfredericks: oh fark

17:27 amalloy: TimMc: you don't have to

17:27 gfredericks: yeah I guess I was doing that

17:27 cemerick: technomancy: hah, until a few minutes ago, I thought there was :-)

17:28 technomancy: well there you go =)

17:28 amalloy: cemerick: technomancy's camp is in the minority, but exists

17:28 gfredericks: amalloy: what can we do to eliminate them?

17:28 cemerick: I shall continue to act in blatant disregard of the minority.

17:28 TimMc: More args, eh?

17:28 gfredericks: can we assume technomancy is their leader?

17:29 TimMc: ah yeah that should work

17:29 TimMc: hurk

17:30 Maybe I can write a macro to convert things to alphanumeric-less style. :-P

17:30 technomancy: there are plenty of places where I question the design of certain built-in Clojure functions, but `if` is not one of them.

17:30 gfredericks: so ((#({a %1} b %2) #(c) #(d)))

17:30 amalloy: (#(% #(%2 %3)) a b c) => (#(%1 %2) a (#(%1 %2) b c)), or something close to that

17:30 TimMc: %2 isn't an option

17:30 gfredericks: oh fark again


17:30 TimMc: Everything has to be a unary function.

17:30 amalloy: oh. well then curry that for me :P

17:30 TimMc: You can build up a nice vector of fns and args and then dereference it.

17:31 gfredericks: TimMc: are you building up a code-transformer for this?

17:31 it begs to be automated

17:32 we can't ever create locals can we? :/

17:32 TimMc: Hmmm, %& would remove the need for unary fns, but dereferencing it requires vec'ing.

17:34 seanm: Does anyone have a moment to help me w/ getting some awesome clojure-mode/swank stuff workin' ?

17:34 TimMc: &(#(+ (`[~@%&] (+(*)(*))) (*)) 10 20 30 40 50)

17:34 lazybot: ⇒ 31

17:34 seanm: On a fresh emacs install with clojure-mode I'm getting these entries in messages https://gist.github.com/743e0fe8b44b75630a9e

17:34 seems like something's not quite lined up

17:34 gfredericks: TimMc: nice

17:35 TimMc: Not wirth it,

17:35 gfredericks: do we know if it's turing complete yet?

17:35 qubit[01]: yall use clojars ?

17:35 gfredericks: qubit[01]: yes

17:35 hyPiRion: Guys, I thought we were going away from perl-like syntax.

17:36 qubit[01]: yes please

17:36 TimMc: gfredericks: Seems Turing-complete. I can pass fns around, yeah? Once you get that it's probably all good.

17:36 gfredericks: I guess that has to be true

17:36 no wait

17:36 in lambda calc you get locals

17:37 you have to have

17:37 lambda (x) -> lambda (y) -> x

17:37 can we do that?

17:38 TimMc: Sure. In Clojure-minus-AN, fns just have to be given everything as args.

17:39 gfredericks: we can simulate closures with arguments?

17:39 amalloy: gfredericks: clojure simulates closures with arguments :P

17:39 TimMc: I... think so?

17:39 Just convey everything explicitly.

17:40 hyPiRion: Well.

17:40 (let [a b c d] ...) => ((fn [a c] ..) b d)

17:40 gfredericks: TimMc: so can you create something that acts like (fn [x] (fn [y] x))?

17:41 amalloy: unary arguments? :P :P

17:41 TimMc: gfredericks: We have n-ary.

17:41 It's just ugly, or simulated with argvecs.

17:41 gfredericks: oooh right

17:41 that might do it

17:42 * gfredericks thinks

17:42 gfredericks: it's like reverse-lambda calc. We simulate currying through multi-arity functions :)

17:42 TimMc: haha

17:43 gfredericks: so if you see a function that has a free variable, you convert it to an additional argument

17:44 sweet we have unlimited locals now

17:44 TimMc: That would seem to be the only way.

17:44 gfredericks: TimMc: truely you are a pioneer

17:44 augustl: is there a canonical JSON parser and writer for clojure?

17:45 * TimMc starts a #clojure-without-alphanumerics channel called "#".

17:45 gfredericks: augustl: there is one for people who care about performance and another for people who like their libs to have "clojure" and "json" in the name

17:45 technomancy: haha

17:45 brainproxy: augustl: have you looked at cheshire?

17:45 llasram: Weren't all the data.json performance problems fixed?

17:45 treehug`: augustl, probably clojure.data.json

17:45 gfredericks: llasram: I wouldn't know

17:45 augustl: gfredericks: jackson? :)

17:46 brainproxy, treehug` looking those up, thanks

17:46 gfredericks: augustl: I was referring to cheshire and clojure.data.json

17:46 augustl: I see

17:47 amalloy: TimMc: you could hang out in #()

17:47 llasram: I haven't seen comparisons between cheshire and data.json, but data.json got a ~10x speed-up about 9 months ago

17:47 Https://groups.google.com/d/topic/clojure/gOrDeQ9bxl4/discussion

17:47 S11001001: ,'#()

17:47 clojurebot: (fn* [] ())

17:48 technomancy: llasram: pretty sure all the 10x speedups possible from jackson happened years ago

17:48 llasram: haha

17:48 Raynes: amalloy, TimMc: Hahaha, I and some friends created that channel like 5 years ago and used to hang out in it.

17:48 I kid you not.

17:48 gfredericks: technomancy: next step -- quantum json parsing

17:48 amalloy: i know, dude

17:48 gfredericks: Raynes: wait how old were you then?

17:48 llasram: Ok, ok, there are benefits to leveraging existing well-tested/-supported JVM libraries

17:48 amalloy: i spent some time in there before #sexpbot existed

17:49 Raynes: gfredericks: 5 years younger than I am now, assuming it actually was 5 years ago.

17:49 llasram: but directly deserializing into Clojure data structures is nice

17:49 gfredericks: so 14?

17:49 Raynes: gfredericks: Think that'd make me 13.

17:49 gfredericks: it's really weird to think that I have a "Rayne's Age" register in my brain somewhere

17:49 Raynes: amalloy: Oh yeah, I guess you did.

17:50 gfredericks: Raynes: you have had a physical effect on me

17:50 llasram: technomancy: Oh, BTW, the uberjar'd data_readers.clj error I'd mentioned a while ago (it just now working at all, vs just not having sane merge behavior) turned out to be Yet Another Hadoop Issue

17:50 amalloy: he hears that a lot

17:50 Raynes: I have that effect on fredericks.

17:50 Cheiron: Hi, any body knows why I'm getting this when trying to bootstrap clojurescript? http://pastie.org/4170908

17:51 treehug`: Cheiron, tried removing the zip file and trying again?

17:51 Cheiron: yes

17:52 treehug`: Cheiron, do you know where it downloads that from?

17:53 Cheiron: don't know really. I cloned clojurescript and tried to bootstrap it

17:53 it supposed to get it from Google Code?

17:53 dakrone: llasram: if you are curious about the speed, check out cheshire.test.benchmark (spoiler: cheshire is still faster)

17:54 treehug`: Cheiron, the one i have has sha1sum 4fac42c4921db7f97bdf672f71613a4a4b1f8c50

17:54 dnolen_: Cheiron: hmm, someone else metioned this before, but the url we're curling definitely exists and works.

17:54 Cheiron: it looks that I'm having a problem when downloading it from google code

17:57 llasram: dakrone: Oh, cool beans. Thanks for the pointer!

18:03 solussd_: what exactly happens when I assoc a new key with a record that doesn't exist in the defrecord type?

18:04 S11001001: you keep record type and it gets stuck on the map

18:04 you lose record type if you dissoc a key that's part of the type

18:05 solussd_: S11001001: what, if any, are the performance implications of adding a key?

18:05 S11001001: normal map assoc cost plus a record copy

18:05 solussd_: hmm.. how does it add a key to the record/map though? Aren't record fields Class ivars?

18:06 S11001001: generic map field

18:06 TimMc: ,(#({} % 5) 8)

18:07 clojurebot: 5

18:07 TimMc: gfredericks: ^ constant fn

18:07 gfredericks: TimMc: nice

18:09 emezeske: Cheiron: Do you have a specific reason to use the clojurescript compiler directly? If not you might have an easier time with https://github.com/emezeske/lein-cljsbuild (disclosure: I am the author)

18:12 TimMc: &(#((% (+(*))) %) [(+ (*)(*)(*)(*)(*)(*)(*)) #(({(+) (% (+(*)(*)))} (% (+)) (% (+(*)(*)(*)))) %) #({} % (+(*))) #(* ((% (+(*))) [(- (% (+)) (+(*))) (% (+(*))) (% (+(*)(*))) (% (+(*)(*)(*)))]) (% (+)))])

18:12 lazybot: ⇒ 5040

18:12 Cheiron: emezeske: will have a look at it

18:12 thank you :)

18:13 TimMc: ...and I'm done.

18:13 amalloy: Damn, this could have been a 4clojure question. :-)

18:13 augustl: this last line is quite intensive.. Any suggestions for improvements? http://pastie.org/4189686

18:14 treehug: emezeske: nice work on cljsbuild - can't imagine messing with the cljs command directly

18:14 amalloy: (-> (handler request) (update-in [:body] json-render) (assoc-in [:headers "Content-Type"] "application/json"))

18:14 brehaut: augustl: assoc-in ?

18:15 or that

18:15 augustl: it turns {} or {:headers {}} into {:headers {"Content-Type" "application/json"}}

18:15 oh, nice

18:15 emezeske: treehug: Thanks!

18:16 Raynes: augustl: https://github.com/noir-clojure/lib-noir/blob/master/src/noir/response.clj#L30

18:16 pdk: ok

18:16 3rd time's a charm so

18:16 any idea why this piece of code would fail to compile throwing a null pointer exception on line 17? http://pastebin.com/RJaLUGp1

18:17 amalloy: i'm guilty of writing that before myself, but you should just use one that someone else wrote, augustl (like Raynes's link)

18:17 augustl: ah I forgot how the threading macro automatically inserts the 1st argument for lists

18:17 Raynes: not using noir ;)

18:17 Raynes: lib-noir != noir

18:17 It is standalone.

18:18 Anyways, this might not be useful to you anyways.

18:18 It isn't middleware.

18:18 However, I'd love to see a pull request adding that middleware.

18:18 augustl: ah, nice

18:18 Raynes: To noir.util.middleware.

18:19 hiredman: pdk: there is no :where

18:19 hyPiRion: only :when

18:19 pdk: oh that figures

18:19 i was staring at it for a couple days wondering why

18:19 cause it throws the error on the line that defines i in that doseq as opposed to the :where

18:20 WELP mystery solved and it compiles

18:20 here i thought i was holding the COMPILER BUG SCANDAL OF THE CENTURY

18:21 augustl: are there any writeups on combining .clj and .java? I'm writing a HTTP API that will index and query Lucene, thought I'd might as well write the Lucene stuff with pure Java. I'm new to JVM stuff so I'm basically looking for best practices for a hybrid project I think.

18:21 alternatively, convince me I should use java interop and write the lucene stuff in clojure :)

18:22 technomancy: https://github.com/weavejester/clucy

18:22 augustl: well well now

18:23 amalloy: technomancy: i was just thinking about your desire to have (filter coll) be equivalent to (filter identity coll). i've previously been in favor, but doesn't that make it harder to read in a context-free way? that is, when i see `(filter (foo)`, i can't know whether foo is a function or a collection until i check whether there's something after it

18:23 pdk: best practices for a hybrid project is basically "what gets the job done"

18:23 augustl: a convincing argument for doing it all in Clojure then :) Even if I won't use that library, the code for it seems sensible etc.

18:23 technomancy: amalloy: that's the one drawback; I hate it when optional args aren't at the end of the arglist

18:23 augustl: pdk: I'm mostly curious how to set up leiningen, how to "link" things, etc

18:24 technomancy: augustl: usually setting :java-source-paths in project.clj is all it takes

18:24 hyPiRion: augustl: To answer your question though, in a leiningen project it's just adding a :java-source-paths option in project.clj

18:24 augustl: technomancy: oh, that was simple. Then I suppose I just follow the traditional package name folders etc?

18:24 technomancy: jinx

18:24 augustl: s/simple/easy/

18:24 hyPiRion: bummer.

18:24 technomancy: augustl: I guess; I don't know the Java Programming Language™ myself

18:24 augustl: :)

18:25 hyPiRion: augustl: yes.

18:25 augustl: I'm dangerously close to using Clojure at work now \o/

18:27 solussd_: anyone here use monger? Wondering what the point of the monger.result namespace is if any error throws an exception

18:28 zellio: what did clojure.contirb/cond-let get replaced with? if anything

18:28 or was it let-cond

18:28 ...

18:28 technomancy: amalloy: in general confusion is less likely with a maximum of 2 args, but on the other hand filter is everywhere... I dunno.

18:29 amalloy: technomancy: i almost feel like i'd rather require filter have exactly two args, and overload keep instead, since nobody really uses keep as it is

18:29 technomancy: I could go for that

18:30 I was hoping to see it on every? and take-while too though

18:31 amalloy: yeah, i know

18:37 zellio: nevermind that will work

18:42 jweiss: anyone use slimv here? trying to set a coworker up with it, and it seems to be completely haywire - repl fires up fine, i can eval and all that, but tab completion dumps text into the repl buffer and it just stays there, screwing up my input.

18:42 aperiodic: i use it, but i'm certainly not a pro and haven't run into that particular issue before

18:43 jweiss: aperiodic: when you do tab completion, where do the completions show up?

18:43 (or just type a function call, it shows the arguments)

18:43 augustl: I'd like to write automated tests for my HTTP api by spinning up a server and assert on actual HTTP requests. Any suggestions for how to do that?

18:44 jweiss: for me they show up on the line beneath where i'm typing in the repl, and they keep building up, and never go away

18:44 augustl: all I know about testing is "lein test" which automatically runs the tests themselves. I suppose performing HTTP requests is easy. So the only hard part is starting (and stopping) the server I suppose.

18:45 aperiodic: jweiss: the tab completion disambig shows up in a little menu like one would expect; docs and fn arity descriptions show up in a pane on the bottom of the vim window

18:47 jweiss: aperiodic: huh, ok that is what i thought should happen. doesn't work that way for me. i must be missing soemthing.

18:47 aperiodic: jweiss: well, docs show up in a pane, fn arities are in the status/cmd line

18:48 jweiss: aperiodic: and this is plain vim, not gvim, right?

18:48 aperiodic: jweiss: yup

18:48 jweiss: maybe try slimv in a clean vim setup (no other plugins)?

18:49 jweiss: aperiodic: i never used vim before, so it was clean

18:49 AFAIK

18:49 aperiodic: huh

18:49 technomancy: augustl: https://github.com/xeqi/kerodon

18:49 it won't start an actual HTTP server, but it's just as good for most cases and much simpler

18:50 augustl: technomancy: the reason I want an actual HTTP server is 1) I've had issues with mocks being too dissimilar to the actual stuff (Rack in Ruby) and 2) I can change how I implement my API without changing the tests

18:50 technomancy: that's really not a problem with ring

18:50 augustl: kerodon seems really awesome though, but mostly for web pages, not APIs

18:52 technomancy: is it possible to add global before-run and after-run hooks to "lein test"? Or perhaps I could make my own test runner in the form of a lein plugin?

18:52 aperiodic: jweiss: you could also try stealing the vim setup from my dotfiles (https://github.com/aperiodic/dotfiles)

18:52 augustl: technomancy: I'll just read the docs, nvm :)

18:52 technomancy: augustl: if you're going to do something like that you should use clojure.test fixtures

18:52 but you shouldn't really do that; just work at the ring level

18:53 if you can't trust ring you can't trust anything

18:53 weavejester: technomancy: Can I quote you on that? :)

18:54 augustl: it rhymes too :D

18:54 technomancy: weavejester: I expect to see it on all your flyers and promotional mailings from here on out

18:55 jweiss: aperiodic: so you are happy with slimv, you don't find it horribly buggy? just making sure it's my setup that is busted

18:55 will try your dotfiles

18:55 weavejester: technomancy: Let's not push it ;)

18:56 aperiodic: jweiss: oh, i might be misunderstanding your problem. I never type directly in the REPL buffer, I only eval stuff from the file(s) I'm working on

18:57 augustl: technomancy: do I have to package stuff into a plugin to leverage hooks? Or can I have project-local plugins/hooks without a separate project?

18:57 technomancy: weavejester: ever since my Joy of Cooking joke made it onto the back of the Joy of Clojure I guess I've had my expectations inflated.

18:58 augustl: if you want the server it in a separate process from the tests, it should go in a lein plugin; otherwise it should be used as a library integrated into your tests

18:59 aperiodic: jweiss: the REPL buffer does do a few odd things if I type in it directly, but not what you describe

18:59 augustl: technomancy: and a lein plugin means publishing it on the interwebs, etc?

18:59 technomancy: right

19:00 weavejester: I wonder if trying to cover the basics of Ring and Compojure in a 40 minute presentation means I'll go too fast...

19:00 I'm tempted to cut out some slides

19:00 technomancy: weavejester: where?

19:01 weavejester: technomancy: I've been talked into a presentation that's tomorrow :)

19:02 technomancy: what's the audience?

19:02 weavejester: technomancy: Varied. Likely everyone knows at least a bit of Clojure. Some will have used Ring, others won't.

19:03 augustl: weavejester: for me, the coolest part of ring and compojure is that it's in Clojure.. So if I were to hold a presentation like that, I'd show off neat clojure tricks.

19:03 weavejester: augustl: Well, it's more an explanation of the technology behind it

19:04 technomancy: I'd focus on the fact that everything is a function. I recently had to tie together two separate defroutes invocations and I really appreciated the fact that it was as simple as (sub/app req) to delegate it off

19:04 I don't think you can do that with stuff like noir, so it's where compojure really shines.

19:05 pendlepants: anyone know how to update the version of clojure being used by 'lein repl'? I'm on leiningen 1.7.1, and it's using clojure 1.2.1 when I run 'lein repl'

19:05 augustl: weavejester: like the bindings to the JVM stack etc?

19:05 brehaut: also: parametric route definitions

19:05 weavejester: technomancy: That's actually pretty much the theme of the talk

19:05 technomancy: excellent =)

19:05 pendlepants: run `lein repl` in a project

19:05 weavejester: technomancy: I explain Ring, then show how middleware is just higher order functions, then show how Compojure is made up of cascading handlers

19:05 brehaut: weavejester: i think that would be a great intro, and totally achievable

19:06 pendlepants: thanks technomancy.

19:06 augustl: weavejester: what technomancy said, I nerdgasmd when I realized that "dynamic" routing was as simple as this http://pastie.org/4189931

19:06 akhudek: technomancy: that's my main complaint with noir. It seems to tie things together in a way that loses flexability.

19:06 weavejester: Then the last bit will talk about structure - how to use group together routes so you can apply middleware or a context to a subset

19:06 technomancy: weavejester: drawbridge might be a nice demo of the flexibility of the HOF approach

19:08 weavejester: technomancy: I don't think I have too much space for that

19:08 technomancy: But it's a good idea to include in a future talk

19:09 technomancy: I want to do something that compares classic MVC with a more functional approach… but that's a later presentation.

19:12 technomancy: yeah, definitely

19:12 lynaghk: weavejester: please record a screencast of that talk, if you're going to put it together.

19:12 adu: lein is magic

19:12 lynaghk: weavejester: that's something I've been very interested in lately.

19:13 weavejester: lynaghk: Skillsmatter is usually pretty quick to upload videos of talks

19:13 lynaghk: And if not, I'll record a version myself :)

19:13 lynaghk: weavejester: I'll keep my eyes posted on it. Do you have an event where you're giving the MVC/FUN talk? Or it's just on the agenda?

19:14 weavejester: I should have time to do that when I finish up my notice period and leave my current job

19:14 lynaghk: No, that's just an idea I want to do

19:15 technomancy: weavejester: where are you going?

19:15 weavejester: technomancy: The plan is to be 50% working on my own projects, 50% contracting

19:16 technomancy: I haven't actually had time to really use the libraries I've written, which I really really want to do :)

19:16 technomancy: good luck!

19:16 lynaghk: weavejester: you have any interest in doing cljs stuff?

19:16 xeqi: augustl: my peridot library is less html specific, but still stays within ring

19:16 technomancy: I know what you mean about getting out of touch with real-world usage patterns.

19:17 weavejester: technomancy: Thanks!

19:17 xeqi: augustl: I think cemerick's friend has some tests that spin up jetty and use a clojure http library

19:17 weavejester: lynaghk: I'm planning to use cljs heavily in a web app I've been intending to write.

19:18 lynaghk: weavejester: web app = lil' product of some kind?

19:18 (or big product.)

19:18 weavejester: lynaghk: That's the idea

19:19 I want to do some experiments with communication protocols

19:20 wingy: why isn't the shell/code in datomic using clojure

19:23 augustl: xeqi: is that open sourced and available somewhere?

19:24 xeqi: augustl: https://github.com/xeqi/peridot or https://github.com/cemerick/friend/blob/master/test/test_friend/functional.clj ?

19:27 augustl: xeqi: so cemerik's friend wasn't a person, but a project :)

19:28 xeqi: augustl: there is also https://github.com/semperos/clj-webdriver/ but not sure if you can just get the http requests from it

19:29 augustl: xeqi: very useful, thanks

19:29 xeqi: .. he might have some friends too

19:48 augustl: xeqi: having the fixture in a separate file is proving to be quite the challenge :)

19:48 namely, starting at port 0 (read: get port assigned from OS) and somehow passing that port number onto the tests

19:51 gfredericks: global variables to the rescue!

19:53 augustl: yay, `declare` to the rescue

19:53 gfredericks: thanks :)

19:54 gfredericks: augustl: oh any time

19:54 augustl: it's a shame clojure.test doesn't allow passing of arguments to test functions

19:54 that's my real problem I suppose

19:55 that is, a fixture for my tests creates a value the tests need to know about

19:55 gfredericks: :(

19:56 augustl: the fixture API is kind of weird..

19:59 gfredericks: I think it's pretty straightforward with the exception of what you've already pointed out

20:34 zippy314: Hi, I've just updated an old clojurescript project to use cljsbuild, but now when when I launch my webapp, the javascript console complains that it can not find my files i.e. "goog.require could not find: myproj.core" Has anybody had any trouble updating to use cljsbuild?

20:35 dnolen: zippy314: are you compiling to a single file? i.e. using at least :whitespace optimizations?

20:35 zippy314: yep

20:36 dnolen: zippy314: are you using goog.require on your index.html page?

20:38 getting warmer on cKanren ... can run basic constraints now.

20:39 zippy314: dnolen: yes, here's a clip from the html: http://pastie.org/4190263

20:41 emezeske: zippy314: does your directory structure match the namespace structure in your clojurescript files?

20:47 zippy314: emezeske: not sure what you mean. do you mean the directory structure of the javascript files in my htdocs?

20:48 emezeske: zippy314: Sorry, I mean is a file with e.g. (ns a.b.c) in .../a/b/c.cljs as opposed to just .../c.cljs ?

20:49 wingy: anyone here having experience with datomic using clojure?

20:49 zippy314: emezeske: no, actuall all the files are in a "src" directory, but have a namespace "ss.X" where x is the filename.

20:49 emezeske: so I should rename that from src, to ss?

20:50 dnolen: wingy: a little.

20:51 wingy: it seems that clojure is not prioritized in the doc atm

20:51 there is an API for clojure but not much more

20:52 dnolen: wingy: it's not, though there are a lot of examples in the datomic directory, and lots of examples on the datomic mailing list.

20:52 emezeske: zippy314: You don't want to rename it; just create a subdir like src/ss/X.cljs

20:53 wingy: dnolen: ok found some examples in the directory and online

20:54 do you know how to start up the shell for clojure?

20:54 dnolen: wingy: you don't need to start up a shell, just connect directly.

20:54 wingy: i mean a repl env where i can test out different commands like in java

20:55 oh

20:55 i see

20:57 dnolen: eg. i wanna run this in the repl: https://gist.github.com/3036704

20:57 but how do i let "lein repl" know where datomic.api namespace is located

20:58 dnolen: wingy: put the datomic jar on the classpath

20:58 wingy: by making datomic a project dependency.

20:59 wingy: https://gist.github.com/3036709

21:00 zippy314: emezeske: I did that, and now I'm getting an stack overflow error when compiling one of my files, which it did't do before! (http://pastie.org/4190337)

21:08 wingy: dnolen: it says jar cant be found

21:08 this one: [com.datomic/datomic "0.1.3099"]

21:08 i have to set up a private repo?

21:10 emezeske: zippy314: hmm, lein-cljsbuild is using [org.clojure/clojurescript "0.0-1424"] at the moment, is that the same as what you used before?

21:11 zippy314: also, are there any symlinks or anything, in your directory structure?

21:13 dnolen: wingy: oh, I probably installed it locally.

21:13 wingy: datomic readme in folder has instructions

21:14 zippy314: emezeske: here's what's weird, I just re-cloned clojurescript directly from github, and did the compilation manually: ".bin/cljsc ss/ > ss.js" and then moved the resultin ss.js file and out directory to the right places and it worked! But I'd much prefer to be using cljsbuild.

21:15 emezeske: zippy314: Well, that's just because lein-cljsbuild won't actually build stuff unless the output mtime is less than that of all the input files

21:15 zippy314: emezeske: I was doing a cljsbuild clean each time...

21:16 emezeske: zippy314: I mean, that's the reason that moving ss.js to the right places made things work

21:16 wingy: dnolen: the README says i have to install it to a local maven repo .. that is a must?

21:16 zippy314: emezeske: but why would I be getting a stackoverflow durring compilation?

21:17 dnolen: wingy: if you want lein to work w/o copying the datomic.jar everywhere - yes

21:17 emezeske: zippy314: That's why I was asking about symlinks. Obviously somewhere there's an infinite loop happening

21:17 zippy314: emezeske: no symlinks

21:18 emezeske: zippy314: any cyclic dependencies?

21:18 zippy314: emezeske: maybe, I'm hunting for that now...

21:18 emezeske: zippy314: you've hit a very strange problem :)

21:19 zippy314: emezeske: your telling me!! :-)

21:22 wingy: dnolen: i rather note maintain a maven repo .. i added datomic-0.1.3164.jar to my resources/ folder .. and according to the class path that folder is added

21:23 but when i run: (use '[datomic.api :only [q db] :as d])

21:23 it still cant find it

21:23 any idea what the issue is?

21:23 dnolen: wingy: why not, you're maintaining them by using lein

21:24 wingy: lein works over maven

21:25 zippy314: emezeske: ok, here's something weird. When I restore the files to their original configuration (i.e. not inside the ss directory to match the ns) and I run cljsbuild, I just noticed that it gives me this error message: http://pastie.org/4190434

21:26 TimMc: Raynes: Clojail doesn't allow defn, yeah?

21:26 zippy314: emezeske: but it actually does complie everything.

21:27 TimMc: Raynes: I'm thinking of writing a sandboxer that whitelists a large number of core fns and macros and checks that only certain namespaces and vars are used.

21:27 zippy314: emezeske: and puts the ss.js file and the out files in the right places, they just don't work! And of course this is really odd to me because compiling it the manual way does work and does not complain about a circular reference!

21:28 Raynes: TimMc: Clojail can allow defn. Just depends on what tester you sue. lazybot doesn't allow it, but tryclj does.

21:28 use*

21:28 TimMc: Can it allow ns?

21:28 Raynes: ns?

21:28 clojurebot: ns is unfortunately more complicated than it needs to be, but http://blog.8thlight.com/articles/2010/12/6/clojure-libs-and-namespaces-require-use-import-and-ns may be helpful.

21:29 wingy: dnolen: ok that worked well .. just a oneliner :)

21:29 TimMc: I need something that can safe-require entire .clj files and call fns in them.

21:29 dnolen: wingy: ;)

21:29 wingy: have fun, datomic is neato.

21:30 wingy: yeah .. converting from neo4j :)

21:30 Raynes: TimMc: You can use require in the sandbox.

21:31 TimMc: Raynes: OK, close enough. I can preprocess any (ns ...) stuff out.

21:31 Raynes: TimMc: Regarding whitelists, you can probably add support for whitelists to clojail.

21:31 TimMc: Raynes: The use-case is a server where people can submit bots to play a game against each other.

21:32 Raynes: I'd strongly recommend not writing your own sandboxer and just trying to make clojail work.

21:32 You'll want to kill yourself if you don't.

21:32 TimMc: heh

21:32 Raynes: I'll happily except patches to add features/functionality that doesn't completely change how clojail works (as in, keeps compatibility with existing code).

21:33 TimMc: Sweet.

21:33 I'm going to propose adding whitelists at the next baznex meetup.

21:34 Raynes: Cool

21:36 TimMc: Raynes: Clojail just inspects the post-expansion syntax, yeah?

21:41 I was pondering writing something that looks at pre-expansion syntax instead, and forces it to conform to a language subset.

21:43 emezeske: zippy314: You've got me!

21:45 zippy314: All I can say is that you definitely want the dir structure to match the ns. I'm not sure why the compiler works without that; it seems accidental

21:45 * emezeske steps out.

21:49 kovasb_: emezeske: hey i have a q about cljsbuild

21:51 emezeske: i'm trying to define my own tagged literals in cljs. seems that i need to change the value of cljs.tagged-literals/*cljs-data-readers* when cljsbuild does its work

22:41 frozenlock: Is there a recursive merge? Say I have {:a {:b {:c 2}}} and {:a {:d 2 :b {:z 3}}}, I would like to obtain {:a {:d 2 :b {:c 2 :z 3}}}.

22:44 wingy: it feels far better to use clojure than java for datomic .. they have to create the queries in strings whereas in clojure you just use the regular data structures

22:44 TimMc: frozenlock: merge-with and a function that calls merge-with, perhaps

22:45 frozenlock: I found http://clojure.github.com/clojure-contrib/map-utils-api.html, but I was hoping for something in .core :(

22:45 wingy: pretty awkward for a java dev: http://www.datomic.com/company/resources/data-structure-literals

22:45 but perhaps they are used to it

22:45 dnolen: wingy: probably.

22:46 TimMc: frozenlock: When keys collide, are the vals always both/neither maps?

22:47 And how do you resolve conflicts on non-map collisions?

22:47 frozenlock: TimMc: yes, the merge will be with 2 identical datastructure

22:48 TimMc: &((fn f [a b] (if (and (map? a) (map? b)) (merge-with f a b) (throw (Exception.)))) {:a {:b {:c 2}}} {:a {:d 2 :b {:z 3}}})

22:48 lazybot: ⇒ {:a {:d 2, :b {:z 3, :c 2}}}

22:49 frozenlock: Oh! Clever!

22:49 Thanks :)

22:50 I especially like the throw error part; I could easily forget about that

22:50 TimMc: You could also just leave it out if you're really sure of yourself. :-P

22:50 frozenlock: With time I learned to never trust myself :P

22:51 TimMc: Heh, good on you. :-)

22:51 Now I'm trying to figure out how to convey path information down into that error message.

22:52 I guess you can't, since merge-with doesn't tell you what key is in conflict.

22:53 It's not a hard function to replace, of course.

22:53 frozenlock: Let's rewrite Clojure!

22:53 When I'm done rewriting Emacs, of course

22:53 brehaut: in clojure!

22:54 frozenlock: Emacs in clojure could be interesting...

22:54 Emacs (in clojure (in clojure)) would be terrific :)

22:55 xeqi: TimMc: I'm interested in you're bot game, is it going to be public?

22:55 TimMc: frozenlock: Emacs in Emacs.

22:56 xeqi: The code is in a public repo: https://github.com/baznex/crosscram/

22:56 tmciver: Crap, I forgot you had a pull request!

22:57 frozenlock: TimMc: I would like that. I hate it when I want to read the source of a function and it simply says "C source code"

22:57 brehaut: i wish it said [madness ensues!] instead

22:58 amalloy: [Here there be dragons]

22:59 brehaut: [ia! ia! cthulhu ftaghn]

23:00 amalloy: frozenlock: you might like useful.utils/adjoin, which is related to the deep-merge you seem to be trying to do

23:00 it deals with sets and vectors in a reasonably-sensible, although not inarguably-correct, way

23:12 emezeske: kovasb_: there's no way to do that without modifying lein-cljsbuild, if that's your question

23:12 kovasb_: I see that you just forked it, so I take it that you figured that out :)

23:12 kovasb_: emezeske: yup :)

23:12 should be easy right

23:12 ;)

23:12 emezeske: yeah

23:14 TimMc: xeqi: Are you in the Boston area by any chance?

23:14 kovasb_: i think i just need to modify run-compiler to require and run the needed code

23:14 TimMc: xeqi: If so, you should come to the next baznex meetup. :-)

23:14 emezeske: kovasb_: sounds right

23:15 kovasb_: great. now i just need to create the needed code.

23:20 wingy: what is the difference between vector and tuple?

23:21 brehaut: i dont think there is a standard tuple type in clojure? hiredman has one in his github i think?

23:21 most clojure code uses vectors as both vectors and tuples

23:21 wingy: brehaut: no i keep hearing about tuples all the time so i wonder what that is

23:21 but what is the difference?

23:21 frozenlock: &,(keyword 2)

23:21 lazybot: ⇒ nil

23:21 brehaut: well a tuple is a heterogeneous collection of a fixed size

23:22 frozenlock: ...

23:22 brehaut: wingy: s an n-tuple where 2=2 is a pair, n=3 is a triple

23:22 frozenlock: I want :2, not nil -_-

23:22 brehaut: &(-> 2 str keyword)

23:22 lazybot: ⇒ :2

23:23 frozenlock: Thanks. So you _have_ to convert it to a string beforehand?

23:23 brehaut: appears to be the case

23:23 wingy: 2-tuple is [[1 2][1 2]]?

23:23 brehaut: no, a 2-tuple is [1 "two"]

23:24 well, your example could be a 2-tuple as well

23:24 wingy: 3-tuple is [1 2 3]?

23:24 brehaut: yes

23:25 wingy: so that is kinda like arrays in other langs?

23:25 brehaut: no

23:25 its most like a record in an SQL database

23:25 xeqi: TimMc: nope, but thanks for the invite

23:25 wingy: ok

23:26 brehaut: or if you are used to javascript, arguments (the magic local variable in functions) is a tuple of the arguments to the function

23:26 frio: wingy: in practical terms, tuples are of a set length - a 2-tuple will always be 2 items long

23:26 and they're probably immutable

23:26 TimMc: And you don't "conj onto" a tuple, either. You just build one or take it apart.

23:26 frio: when you're using them though, their APIs generally match those of a list :)

23:27 TimMc: Well, maybe that depends on the language.

23:27 brehaut: a common example is returning multiple things from a function

23:27 frio: (other than the fact that yeah, you can't add elements etc. onto them)

23:27 for sure TimMc

23:27 im thinking of python, where a list is [1, 2] and a tuple is (1, 2)

23:28 aside from the fact the tuple is immutable, you can still do stuff like (1, 2)[0] to get the first element, etc.

23:28 brehaut: frio: in python a tuple is also a value type (it can be hashed) where a list isnt

23:28 frio: mm brehaut

23:30 brehaut: wingy: its kinda easy to over thing a tuple; its mostly a bunch of different things side by side

23:31 wingy: tuple is an abstract term and not necessarily a specific data type?

23:31 brehaut: right

23:31 wingy: meaning: 1. fixed length 2. immutable

23:31 brehaut: and potentially heterogeneous

23:31 frio: its a mathematical concept :)

23:31 wingy: i c

23:32 in clojure we use vector as a tuple?

23:32 brehaut: yup

23:32 wingy: what about a list?

23:32 brehaut: lists have O(n) access by index

23:32 makes them a poor candidate

23:33 whereas vectors are O(effectively 1)

23:33 wingy: dont know what you did there .. but yeah lists have no indexes

23:33 frio: lists are indexed

23:34 brehaut: eh‽

23:34 frio: oh

23:34 dw

23:34 i see what you mean :)

23:34 brain-fart

23:35 brehaut: wingy: it means if you want to get the 5th item of a list, you have to walk past the first 4 to get it

23:35 whereas a vector you can just go straight to the 5th item

23:37 wingy: yepp

23:43 amalloy: brehaut: tuples are small enough that a list's O(n) would be acceptable

23:44 but they're more convenient, plus you might as well be fast

23:44 "they" [vectors] are ..."

23:44 jesus i'm just a mess. forget i tried to participate

23:47 xumingmi_: join #clojure-cn

23:47 Fare: hi!

23:48 I'm trying to standardize a "collections" / "containers" / however-you-call-it library for common lisp.

23:48 I'd like to have the opinion of clojure people

23:48 you seem to have interfaces already and collections libraries

23:49 where is the docs, what do you like / dislike about it, what were the interesting tradeoffs you made?

Logging service provided by n01se.net