#clojure log - Aug 01 2011

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

0:03 jcromartie: so, with compojure, (resources "/") does not work when running the handler from Swank or a regular REPL?

0:06 amalloy: uh, i don't understand what your question is, but the answer is "that is incorrect"

0:07 jcromartie: ok

0:07 assume I have some routes

0:08 (defroutes my-routes ... (resources "/") (not-found "nope"))

0:08 amalloy: right

0:08 jcromartie: when running with lein ring, it serves up the stuff in resources/public just fune

0:08 fine

0:08 but when I run lein swank and start my dev server that way, it doesn't serve them up

0:09 (files "/") will serve anything in public/ when running from swank

0:09 amalloy: dunno, man. i never use lein ring, but it sounds like it may be doing some magic for you that you should be doing yourself

0:10 jcromartie: yes

0:10 I have to go, but the cursory look I gave to the source indicates that lein ring makes a war and reloads in on change?

0:11 I'll figure it out tomorrow

0:11 until then, (files "/")

0:11 bye!

0:42 st3fan: hm is there a function that merges a bunch of lists? like (foo [1 2] [3 4]) -> [1 2 3 4] ?

0:42 dakrone: ,(concat [1 2] [3 4])

0:42 clojurebot: (1 2 3 4)

0:42 st3fan: ah nice :)

0:43 amalloy: that makes it not a vector anymore, if that's a problem for you

0:44 st3fan: nah that is fine

0:44 b

1:07 leonid_: ,(apply conj [1 2] [3 4])

1:07 clojurebot: [1 2 3 4]

1:08 amalloy: leonid_: :(. use instead ##(into [1 2] [3 4])

1:08 lazybot: ⇒ [1 2 3 4]

1:10 leonid_: amalloy: awesome

1:11 forgot that into does apply conj

1:11 amalloy: leonid_: it actually does reduce conj!

1:11 leonid_: ooh

1:11 amalloy: but the effect is the same

1:11 leonid_: yeah you are right

2:01 MasseR: So majority of clojure datatypes are immuteable, but (def foo bar) creates a Var which is mutable? So I suppose (def foo bar) needs some consideration when used. (Not to mention that global values are usually a bit frowned)

2:02 leonid_: def is blocked on 4clojure

2:04 MasseR: 4clojure?

2:06 leonid_: a site for 4clojure beginners

2:06 to help them learn clojure

2:07 it's a great site

2:07 http://www.4clojure.com

2:07 MasseR: Oh, nice

2:22 amalloy: MasseR: (def foo bar) is generally fine at the top level, since it's creating (mostly) constants

2:23 as a rule though, you shouldn't (def) anything at runtime. fine while you're developing to redefine things as you write better versions of def'd functions, but don't rely on it in finished code

2:23 MasseR: Ok

2:46 hiredman: technomancy: I've started on rewriting the scp bits in clojars to use apache-mina https://github.com/hiredman/clojars-web/tree/mina-sshd

2:47 it accepts files over scp and deploys them to /tmp right now, doesn't check credentials etc yet

3:29 kostrikov: hello from irssi

3:29 ohwow_: Hello

4:48 fhd: Hi

4:48 Is anyone using ClojureScript with Maven yet?

4:51 And if not, can you point me to a typical Leiningen ClojureScript project?

5:00 MasseR: leonid_: Damn you for pointing out 4clojure :D

5:25 How does clojure handle IO concurrency? With explicit threads? Select? Something else?

5:36 pyr: hey

5:38 _ato: MasseR: Clojure core itself does not address IO concurrency. Yes you can use threads or select.

5:39 You might find the Aleph library interesting for async IO: https://github.com/ztellman/aleph

5:39 MasseR: Oh :/. AFAIK haskell IO scheduler uses epoll automatically

5:40 Pupeno: Hello.

5:41 pyr: building a mostly clojure backend for new company from infrastructure to storage to other parts if people are looking for work in switzerland, or maybe remotely, you can leave me a mail at pyr@spootnik.org

5:44 _ato: MasseR: Clojure doesn't have green threads, which is I assume is what Haskell uses epoll for

5:49 MasseR: _ato: So clojure threads are OS threads+

5:50 _ato: What is the clojure thread performance? On haskell it's ok to create >100k threads

5:50 lucca: you can probably check performance reports for java threads.

5:52 MasseR: Apparently, exhausting threads is an issue

5:53 And the limit is relatively low

5:53 But I do see mentions about thread pools. Is it manual on clojure too?

5:54 lucca: you might need to use a different abstraction than on haskell.

5:55 it's not too bad to turn many separate threads to instead be items in a queue of io operations handled by a small pool of worker io threads

5:55 I don't know of libraries for that, though

5:56 MasseR: On haskell I'd just 'forkIO' for every incoming request :P

5:57 _ato: Many Clojure concurrency primitives will use a thread pool by default, like agents and pmap. There's usually the (programmer's) option of creating a thread-per-job for jobs that you expect to block.

5:58 Currently there's no automatic use of select/epoll though. Not a strong story in Clojure core for 100k connection I/O. But there are plenty of JVM libraries for doing that sort of thing like Netty which Aleph builds on top of

5:58 MasseR: _ato: How does the thread pool handle blocking io? A queue of jobs?

5:58 _ato: it doesn't

5:59 MasseR: s/handle blocking io/handle jobs/

5:59 lazybot: <MasseR> _ato: How does the thread pool handle jobs? A queue of jobs?

6:00 _ato: yeah basically. agents tasks queue per agent in the order they were sent. pmap queues well, it's a parallel sequential map so it just queues in the order of the sequence you're mapping over

6:01 etc

6:03 MasseR: So the hype about clojure concurrency is about how easy it is to reason (STM), not necessarily the performance?

6:15 raek: MasseR: lock free reads might count as a performance argument

6:15 but program correctness for concurrent programs is a big thing

6:18 I recomment checking out ExecutorService and related classes

6:18 http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html

6:19 I made a small introduction on how to use them from clojure: http://blog.raek.se/2011/01/24/executors-in-clojure/

6:20 MasseR: thanks

6:21 raek: CompletionService might be useful too

6:22 _ato: MasseR: right. if you're after ultimate I/O performance there is going to be a lot of better choices than Clojure. Clojure's performance is pretty good (mainly thanks to the JVM's good JIT and GC), but using immutable persistent data structures is of course going to have some performance impact unless the problem is extremely read-heavy.

6:23 raek: but to summarize: JVM threads are heavy so it might not be a good idea to create thousands of threads. but the java standard library has good support for thread pools and these intergrate pretty well with clojure

6:25 MasseR: this book is _the_ book to read if you want to look at these things in detail: http://jcip.net/

6:25 (Java Concurrency in Practice)

6:26 you can pretty much skip the chapters about coding in a thread safe manner, since clojure takes care of that for you :-)

6:28 MasseR: thanks for all of your help. I'm not looking to creating anything (yet), just trying to see how clojure compares :)

6:37 _ato: when compared to Haskell I'd consider the huge JVM ecosystem (in terms of libraries, tools and ops team experience), simple and very cohesive language design, dynamic typing (which might be a con, depending on preferences) and being a Lisp (again a pro for some people con for others) the major comparison points rather than concurrency or performance as Haskell has a pretty good story for those too. Probably Clojure's concurrency model

6:37 is better at certain things and Haskell's at others.

6:39 MasseR: my take on it is the simplicity of clojure and the jvm

6:40 (and also the simplicity of the syntax. erlang is bulky :/)

6:41 fhd: Now that it's more crowded here, I'll ask again: Does anybody know a nice Clojure + ClojureScript project template? Preferably Maven, but I'll take anything.

6:43 _ato: fhd: I assume you've seen: https://github.com/maxweber/cljs-devmode ?

6:44 fhd: _ato: Nope, didn't know that, I'll take a look

6:45 _ato: I haven't tried it, just saw the announcement on the mailing list. I haven't done any Clojure + ClojureScript work yet, just stinkered with standalone ClojureScript a bit

6:45 MasseR: does clojure stm have retry and <|> combinators?

6:45 fhd: _ato: I found plenty of cljs standalone samples, but what I want to do, a Clojure + ClojureScript project, is nowhere to be found

6:48 _ato: MasseR: it will retry a transaction if there's a conflict, if that's what you mean. I don't know the terminology "<|> combinator"

6:49 MasseR: the latter is if a fails try b

6:50 and by retry I meant like "foo or bar or retry" (weird syntax but I'm on mobile atm)

6:52 raek: MasseR: I don't think you can trigger a restart manually in clojure

6:52 MasseR: ok

6:53 raek: MasseR: this is a really good article about the STM: http://java.ociweb.com/mark/stm/article.html

6:54 MasseR: thanks

6:56 triyo: Anyone have some experience in building web pages with Enlive?

6:56 I love the decompiling it offers between the templates itself and the logic.

6:57 however I have come across an interesting problem I am trying to find the best solution for.

6:58 I have a nav.html template for navigation. I have introduced an auth component to the web app and now wish to show/hide links depending on auth.

6:58 This part seems to be a bit tricky at the micro level.

6:59 What would be a common way to do this in enlive?

7:00 typo *decompiling =decoupling

7:00 thorwil: triyo: you could have just one link in the template and clone it depending on a map that is handed over by your controler

7:01 or have all the links in the template and include/exclude with a list of booleans

7:02 triyo: I like the second approach, thanks

7:03 To add to the second approach, I will have all links visible by default and let the template function just supply a list of *excludes*

7:04 thorwil: it's stuff like this that made me switch over to just hiccup, as i had to notice that the html templates alone are bulkier than corresponding hiccup and the enlive template functions i had to write grew in number and complexity

7:05 triyo: thorwil: complexity is what Im starting to see slowly as my app is increasing in size and complexity.

7:05 thorwil: of course, this decision is based on the fact that i write everything myself, anyway

7:06 triyo: I guess the decoupling comes at a price

7:06 _ato: if you have lots of things to show and hide depending on an auth role it occurs to me you could make up a custom attribute to tag them with: <a href="..." role="superadmin"> <div role="manager">

7:06 thorwil: definitively

7:06 _ato: and have enlive remove them as appropriate

7:07 triyo: _ato: exactly. However there is no doubt that it is a bit of a mind shift from traditional thinking when it comes to html templates.

7:07 Thats the part I'm battling with a bit at this stage.

7:08 I think, if one builds the most common html template abstractions on top of enlive, then you are pretty sorted.

7:36 What is the simplest way to to remove/exclude elements from the template. So as _ato suggested, I marked my links with relevant roles (role="admin") and now wish to remove the admin roles when isadmin? auth predicate is false.

7:37 in *enlive* that is

7:38 I know how to create the right selectors, its the transformation step I am missing..

7:38 MasseR: On my last question. With haskell it's possible to for example `if count xs > 0 then return (head xs) else retry`, which returns the head of the list if there is something in there, or otherwise waits until some other transaction has finished. Is this possible with clojure?

7:40 triyo: (if (> (count xs) 0) (first xs) retry)

7:40 thats the the same *if* form in clojure

7:41 MasseR: So there is a retry function? ClojureDocs didn't find it

7:42 manutter: The retry function itself does not exist, but there are transaction-oriented structures in clojure

7:42 depending on the broader context of what you're trying to do, it should be possible.

7:42 (though I'm not sure off the top of my head how)

7:43 MasseR: Rather, I remember Simon Peyton-Jones mentioning that just a simple transaction isn't enough, you need combinators such as retry and or-else, and that was the simplest example I could think of that uses those

7:46 manutter: I can envision a macro something like (defmacro with-retry [pred &body] `(while (?false ~pred) (Thread/sleep 200)) ~@(body))

7:46 with the caveat that I'm not a very good macro writer, and I havent had any coffee in a very long time

7:46 MasseR: Heh

7:47 manutter: but if you had a working version, you could call (with-retry #(> (count xx) 0) (first xs))

7:49 Hmm, that would have limited usefulness, though -- if you had to do a certain amount of calculation before you knew whether a retry was needed or not, there'd be code duplication or other complications

7:50 MasseR: And unless I'm totally mistaken, that's not composable

7:50 Compare to `foo or-else bar or-else retry`

7:50 manutter: You're not mistaken, that's the gotcha with macros

7:50 dnolen: MasseR: seems like a use case better suited to other concurrency constructs? your example sounds like producer/consumer

7:51 MasseR: dnolen: I haven't done much concurrency, not to mention with STM. I have just played a little with haskells STM

7:52 But yes the example earlier is from a simple push/pop channel with lists

7:52 manutter: The retry function reminds me of a conditional recur, so I'd expect it would be possible to write one, but it'd be hairy

7:52 I think the more idiomatic way would be to use the concurrency constructs, like dnolen is saying

7:53 dnolen: MasseR: yeah STM is overkill and inefficient (I think) for something like that. Java queues are designed for high performance consumer/producer

7:53 MasseR: dnolen: I agree. I wouldn't do that in production, but as a simple one-line example I think it's ok

7:54 dnolen: MasseR: I'm sure rhickey just left out features from Clojure's STM that aren't generally useful.

7:55 manutter: Heh, I'm reading thru _Clean Code_ by Uncle Bob Martin, and just got to Chapter 13: Concurrency

7:55 dnolen: or weren't solved (that is couldn't meet reasonable performance criteria)

7:56 manutter: This should be fun :)

8:32 ells: morning to some, evening to others

8:35 triyo: I have a selector as follows in my enlive code.. [(attr= :role "admin")] (if admin? (content "xxx") (content)) ... I admin? is true, I wish to return just the content thats in the template and not "xxx" of course, if admin? is not true, I just return (content).

8:36 Something doesn't seem right. How do I apply conditional login in enlive for a selector?

8:37 So when condition is meat, it should just return what was selected as per selector.

8:37 *login=logic

8:38 well as a matter of fact, I don't need the else part (content) at all of course.

8:41 raek: triyo: content replaces the content

8:42 triyo: I think you want unrwap or something

8:42 also, the right hand side should evaluate to a function

8:43 triyo: (fn [node] (if (admin? node) (unwrap node) nil))

8:44 "Transformations are closures which take one arg (the selected node) and return

8:44 nil, another node or an arbitrarily nested collection of nodes."

8:44 triyo: Oh see what you mean.

8:44 raek: you could replace (unwrap node) with ((remove-attr :role) node)

8:45 MasseR: Damnit. Isn't it enough that haskell ruined php for me, but now even clojure made it even worse :D

8:47 triyo: raek: that worked of course, however, I had to remove the unwrap bit and just return the node if admin? true

8:47 thanks

8:48 raek: triyo: you can use remove-attr as a separate transformation step to remove all "internal" markings of your elements

8:49 [(attr? :role)] (remove-attr :role)

8:49 triyo: raek: ahh, yes to remove non-standard html before sent to the browser. Nice

8:50 non-standard element attributest to be exact.

9:12 phenom_: anyone know why records that implement a protocol dont have to implement all methods?

9:13 dnolen: phenom_: because that's not a good interactive programming experience.

9:43 mattmitchell: any opinions on testing in clojure, and specifically midje?

9:53 jcromartie: mattmitchell: I've been happy with clojure.test so far

9:53 but, wow, midje sure is packed with stuff

9:54 manutter: midje is kinda fun too :)

9:54 mattmitchell: jcromartie: yeah we're using midje now and liking it. some of the devs think it's a little too magical though, so wanted to see what others thought of that.

9:56 manutter: ,(let [passed :), failed :(] (if (> 3 2) passed failed))

9:56 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: Invalid token: :>

9:56 manutter: ,(let [passed :), failed :( ] (if (> 3 2) passed failed))

9:56 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: Invalid token: :>

9:56 manutter: oh well

10:03 jcromartie: I see, so midje lets you do *real* test-first

10:03 i.e. write and compile tests even if the api/functions don't exist yet

10:03 awesome

10:03 a la Smalltalk

10:03 Pupeno: What does (JFrame.) do?

10:04 MasseR: I'd say it creates a new instance

10:04 Pupeno: jcromartie: any dynamically typed language let's you do that.

10:04 well… almost… (just in case)

10:04 MasseR: Hmph I think my lein is borked.

10:05 jcromartie: Pupeno: I'm not sure dynamic typing is the main prerequisite there

10:05 you can't compile Clojure code when the names don't resolve

10:05 so Clojure fails that

10:05 thorwil: wasn't the special thing about test driven devel in smalltalk that you can write the "fixes" inside the debugger?

10:06 jcromartie: thorwil: yes.

10:06 you can implement missing classes and methods from the middle of atest

10:06 it's pretty incredible really

10:06 * jcromartie sneaks off to run Pharo

10:06 jcromartie: Don't tell Emacs I'm cheating...

10:13 phenom_: anyone interested in helping me out on an oss project?

10:15 MasseR: phenom_: I'm sure you'll find helpers if you tell what kind of project it is / show the project page / github

10:15 mattmitchell: jcromartie: yes, you can certainly test first like you mentioned, with midje

10:19 phenom_: sure, give me a shout if you're interested in mq's, nio and stomp http://github.com/djunforgetable/balrog :D

10:55 MasseR: What characters are allowed in function names?

10:55 Chousuke: most

10:56 if you can think of a character having some special meaning elsewhere then it's probably not allowed but all others are

10:56 Fossi: i'd guess those that java allows minus some special chars that are used for the reader?

10:56 Chousuke: Clojure allows more

10:56 like ? and ! and -

10:57 MasseR: Great

12:22 jkkramer: i'm having problems reading data from resources on heroku. has anyone done this successfully?

12:23 i've tried referring to the resource with (str "resources/" filename) and (-> (Thread/currentThread) .getContextClassLoader (.getResource path)), both of which work locally but break when deployed

12:23 hiredman: jkkramer: most likely you are passing the result of (resource ...) to something that can't handle a jar: url

12:24 (most funs in clojure.java.io cannot)

12:24 jkkramer: hiredman: i'm passing it to (read-string (slurp ...))

12:24 it works fine when running on my dev setup

12:25 hiredman: right

12:25 see what I just said

12:26 (.openStream (resource …))

12:26 raek: but clojure.java.io/intput-stream can handle jar urls, right?

12:27 hiredman: I doubt it

12:27 clojure.java.io general blows up (and sometimes blows up very badly) on jar urls

12:27 jkkramer: i guess i'm confused about why it would work when running locally but not when deployed. the heroku environment seems to have some idiosyncrasies

12:28 hiredman: I could be wrong

12:28 raek: jkkramer: using a filepath relative to the project path is probably not gioing to work, unless heroku unzips the jar

12:29 jkkramer: ah right

12:29 raek: opening the resource from the classpath sounds like the right thing to do

12:31 hiredman: (require '[clojure.java.io :as io]) (slurp (io/resource "clojure/core.jar")) works in my repl

12:31 and slurp calls io/reader, iirc

12:31 hiredman: raek: thats not a jar url

12:32 unless you have clojure/core.jar in a jar

12:32 raek: *core.clj

12:32 hiredman: fine

12:32 raek: (io/resource "clojure/core.clj") => #<URL jar:file:/home/raek/.m2/repository/org/clojure/clojure/1.2.0/clojure-1.2.0.jar!/clojure/core.clj>

12:32 that was a typo, sorry

12:33 I was surprised since I was sure that I had used this before

12:34 jkkramer: does (read-string (slurp (io/resource filename))) work?

12:35 (with-open [in (-> filename io/resource io/reader)] (read in)) <-- this avoids the intermediate string

12:36 lobotomy: morning folks. i'm at the point in my project where i think i might need... a variable. but i'm not sure how to proceed :)

12:37 raek: a mutable variable or would a 'let' be enough?

12:37 lobotomy: i'm porting my puzzle solver from java to clojure. in the java version i have a "wireframe" thing which is mutable, onto which are grafted the (clones of edges of) immutable pieces, while the solver proceeds

12:38 i'm thinking i could also do the wireframe immutably: insert new piece -> for each affected edge, create a new amalgamated edge, and update the next-edge pointers from the old to the new one

12:38 jkkramer: raek: still works locally but breaks on heroku

12:38 lobotomy: or i could do it mutably: insert new piece -> for each affected edge, just change its content and leave alone the next-edge pointers

12:39 raek: jkkramer: what does the error say?

12:39 jkkramer: how do you give the app to heroku? as a jar?

12:39 lobotomy: well, in both cases i'd also have to change (in some cases) some of the successor edges, so hmm, immutability would seem to be more complicated here

12:39 jkkramer: raek: java.lang.IllegalArgumentException: No implementation of method: :make-reader of protocol: #'clojure.java.io/IOFactory found for class: nil

12:40 raek: they have a git-based deployment process, with some server magic going on on their end. it's kind of a black box

12:40 lobotomy: so my question is: for a mutable wireframe, should i use a ref or an atom or what?

12:40 raek: jkkramer: ok. looks like io/resource returns nil here. that means that the file is not on the claspath.

12:40 jkkramer: I suspect heroku is not aware of the resources/ convention

12:41 lobotomy: (eventually when i get to multiple threads, each thread would have their own copy of the mutable part of the thing, so i don't need to synchronise that part)

12:41 raek: jkkramer: does it work to have the files in src/ instead of resources/

12:41 jkkramer: raek: it runs the app via leiningen. i could try putting in some explicit project.clj directives...

12:41 raek: hrm. then that idrectory should be on the classpath

12:42 assuming they use leiningen to construct the classpath

12:42 which they might not

12:43 placing resource files in src/ shoud confirm or falsify this theory

12:44 KeithWyss: lobotomy: if you truly don't need to synchronize changes across threads, think of using an agent.

12:44 raek: jkkramer: my theory is that heroku is does not use leiningen to build the classpath, but uses something hardcoded, like 'src/:classes/:lib/*', which does not include resources/

12:45 KeithWyss: lobotomy: http://clojure.org/agents

12:46 drewr: lobotomy: also read through the ants demo code to get an idea of how rhickey solved a similar mutable-world problem (using refs)

12:48 jkkramer: raek: ah jeez, user error. the resource wasn't actually committed due to .gitignore. thanks for your help

12:52 KeithWyss: jkkramer: ouch. That's frustrating.

12:56 Pupeno: Any ideas what I could work on, Clojure related, during a hack day at work?

12:57 technomancy: Pupeno: I recommend clojars

12:57 there's a thread about contributing here: http://groups.google.com/group/clojars-maintainers/browse_thread/thread/d4149ec96316d5b1

12:58 it's probably the #1 highest-profile oss clojure project, but it doesn't get much attention

12:59 Pupeno: I see.

12:59 hiredman: technomancy: I started a branch over the weekend moving to mina sshd (dunno if you saw my earlier msg)

13:00 technomancy: clojurebot: contributing to clojars is a great idea! see http://groups.google.com/group/clojars-maintainers/browse_thread/thread/d4149ec96316d5b1

13:00 Pupeno: Not sure if it's the best as I'm not that knowledged on Java, jars, Maven and so on… but I'll take a look anyway.

13:00 clojurebot: 'Sea, mhuise.

13:00 technomancy: hiredman: yes yes awesome. will try to take a look before thurs.

13:01 Pupeno: there are plenty of pure-clojure features that would be great to have.

13:02 Pupeno: technomancy: I see.

13:06 Quick question, do you know if you can just run clojars locally, without having to setup nginx and so on?

13:06 technomancy: Pupeno: best to run it inside a VM. see the "vagrant" branch on my fork.

13:06 hope to get it into mainline soon

13:11 pyr: when splitting up functionnality

13:11 sometimes it'd be nice to define defmultis in one namespace

13:11 and defmethods in another

13:12 i.e for a caching layer: cache.clj and cache/redis.clj, cache/memcache.clj

13:12 how do you handle dependency in that case

13:12 it seems the sub namespaces need to have the main one as a dependency

13:13 to know about the defmultis

13:13 but then the other way around is true as well

13:13 and circular deps won't work

13:14 wait

13:14 i'm stupid is all

13:14 Pupeno: technomancy: what do you mean by VM? a Linux VM?

13:15 technomancy: Pupeno: yeah. it's easiest to get going with vagrant, which uses virtualbox.

13:15 since you need a bunch of system-level packages

13:16 I don't know if you can populate the DB without running the scp server.

13:17 Pupeno: technomancy: that would be a problem to code.

13:17 I mean… to have a nicely populated db… for some things.

13:17 hiredman: if I finish the scp stuff I'd like to move the db to apache-derby

13:17 technomancy: that would definitely help

13:17 Pupeno: Do you code inside the DB?

13:17 hiredman: there is an sqlite dump you can download

13:18 clojars currently uses sqlite

13:18 technomancy: hiredman: but the dump has passwords wiped, so you can't use it out of the box

13:19 hiredman: mmm

13:19 technomancy: you could probably twiddle it, but I found it easier to just create a new account on a fresh db and do some uploads

13:30 Pupeno: technomancy: do you code inside vagrant?

13:30 inside the vm I mean.

13:31 sjl: Pupeno: Vagrant sets up a shared folder for you, so you can edit in the host OS and the VM will see it.

13:32 technomancy: clojurebot: oracle is currently at threat level yellow: http://steveonjava.com/wp-content/uploads/2011/07/threat-level.png

13:32 clojurebot: 'Sea, mhuise.

13:32 technomancy: Pupeno: I haven't done much with clojars, but for the day job I code mostly inside a vagrant VM

13:32 Pupeno: but it's easy to use the shared folder as sjl mentions

13:51 Pupeno: right now clojars is not the most contributor-friendly codebase; I actually hope to get a chance to smooth things over before the seajure meeting on thursday

13:51 Pupeno: What is seajure?

13:51 technomancy: seattle clojure group

13:52 clojurebot: seajure is the seattle clojure group: http://seajure.github.com

13:52 clojurebot: Ack. Ack.

14:42 kaiser: ,(println "test")

14:42 clojurebot: test

14:43 kaiser: ,(println (+ 41 1))

14:43 clojurebot: 42

14:43 kephale: ,(println ",(println \"test\")")

14:43 clojurebot: ,(println "test")

14:43 kephale: aww : P

14:44 ,(println "&(println \"test\")")

14:44 clojurebot: &(println "test")

14:44 lazybot: ⇒ test nil

14:45 * amalloy waits for kephale's inevitable disappointment at getting it to go one more round

14:46 * Raynes wonders why people always try that when it is obviously impossible.

14:47 kephale: mmm friggin ⇒

14:49 which bot responds to ##(println "test")

14:49 lazybot: ⇒ test nil

14:49 kephale: ah

14:50 * kephale returns to conferencing

14:53 wwmorgan: I'm using enlive to get a piece of parsed HTML like this: {:tag :table, :attrs {:style "..."}}. What's the library or function to reverse this, and give me "<table style='...'></table>"?

14:55 raek: wwmorgan: emit, I think

14:56 or maybe emit*

14:56 wwmorgan: raek: aha. enlive's emit* is what I want. Thanks!

16:04 zvrba: hello. what resources could you recommend for learning clojure?

16:05 tufflax: clojure.org personally

16:06 zvrba http://stackoverflow.com/questions/2578837/comparing-clojure-books

16:07 zvrba: ok, thanks!

16:08 tufflax: zvrba also this http://news.ycombinator.com/item?id=2753467

16:44 triyo: Not sure if anyone will find this useful. In ClojureScript code, I have a config.cljs file with prod and dev tests like so: (def production? (js* "/yourprodsite.com$/.test(window.location.hostname)")) (def development?

16:44 (not production?))

16:44 Pupeno: technomancy: I got clojars running on my mac following the four steps in the read me… what's the issue for using vagrant?

16:47 technomancy: Pupeno: most people don't like to pollute their main machine with the services necessary to get things like that running, especially once you consider that with multiple services you often have conflicting versions required. but if it works in your case, then go for it.

16:47 triyo: I find it pretty neat when switching between dev and prod. I have quite a few public api ajax callouts, so in dev I just call up the mock json data and in prod it calls the live apis.

16:48 technomancy: Pupeno: I guess the other thing is that it's easy for mac-specific problems to sneak in when you're developing on a different platform than you're deploying to. for instance, if you accidentally wrote code that relied on a case-insensitive file system, you would'nt know until it was deployed to clojars.org

16:49 clojureExpertWan: hello

16:49 Pupeno: technomancy: I just run the jar… didn't have to polute everything.

16:50 clojureExpertWan: I am an extreme nub to this language, I would like to change that...

16:50 technomancy: Pupeno: well presumably you had to install nginx and sqlite

16:50 clojureExpertWan: Sooo could anyone help me with something I am having trouble with?

16:50 amalloy: ~anyone

16:50 clojurebot: Please do not ask if anyone uses, knows, is good with, can help you with <some program or library>. Instead, ask your real question and someone will answer if they can help.

16:50 Pupeno: technomancy: sqlite I already had… no nginx.

16:50 jcromartie: hm, looking at FleetDB, it seems that it appends the whole DB when making a snapshot

16:50 that could get quite slow, no?

16:50 instead of appending each transaction to the log file?

16:52 clojureExpertWan: (do (def a ((. javax.swing.JOptionPane (showInputDialog nil "Hello World"))))) #<CompilerException java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn (NO_SOURCE_FILE:1)>...I am trying to get input and it keeps saying this?

16:53 technomancy: Pupeno: also unless you're no ubuntu you can't test the init scripts

16:53 *on Ubuntu

16:53 amalloy: too many (s after a

16:54 clojureExpertWan: no its saying the string cannot be cast...I tried the ^String but I do not know what I am doing obviously

16:55 technomancy: Pupeno: it just depends on what level of fidelity you want re: mirroring production environment

16:55 amalloy: $javadoc javax.swing.JOptionPange showInputDialog

16:55 $javadoc javax.swing.JOptionPane showInputDialog

16:55 lazybot: http://download.oracle.com/javase/6/docs/api/javax/swing/JOptionPane.html#showInputDialog(java.lang.Object)

16:55 technomancy: the more differences there are between the dev environment and production, the more surprises are likely to sneak in at deploy-time.

16:56 clojureExpertWan: I am just trying to see if I can actually assign input from a dialog box

16:56 amalloy: you can. you might have other problems, but one problem is there are too many (s after the a

16:57 clojureExpertWan: lol

16:57 you are right

16:57 wtf__ftw: Is there anyone that can help me debug a ns problem?: http://pastebin.com/599dR9sK

16:57 clojureExpertWan: o my i am a horrible nub

16:57 thank you for your help

16:57 amalloy: wtf__ftw: drop the parens around your namespaces

16:58 * Pupeno is back.

16:58 wtf__ftw: what, like: "(:use my.game)

16:58 ?

16:58 amalloy: clojureExpertWan: suggestion: when you come in saying "i don't know what i'm doing but X doesn't work", and someone says "do Y", don't respond with "no, Y can't be it"

16:58 clojureExpertWan: i did...btw my name is supposed to be clojureExpertWannabe

16:58 amalloy: yes

16:58 Pupeno: technomancy: I code web applications like this all the time… for a living… so yeah, there might be some differences and that's why I normally use staging servers.

16:58 technomancy: what are these init scripts yo talk about?

16:59 amalloy: ~ns macro

16:59 clojureExpertWan: yes I am sorry about that... I guess I thought that I knew better but thank you for being patient

16:59 clojurebot: contains? is for checking whether a collection has a value for a given key. If you want to find out whether a value exists in a Collection (in linear time!), use the java method .contains

16:59 technomancy: Pupeno: clojars uses upstart to manage its daemons

16:59 amalloy: technomancy: dang it, where did you teach clojurebot to say useful things about ns

17:00 technomancy: clojurebot: ns form?

17:00 clojurebot: regular expressions is http://www.regular-expressions.info/tutorial.html

17:00 technomancy: clojurebot: botsmack

17:00 clojurebot: clojurebot evades successfully!

17:00 technomancy: dang iiiiit

17:00 tufflax: lol

17:00 technomancy: clojurebot: the ns form?

17:00 clojurebot: the ns form is more complicated than it should be, but it's better-documented at http://blog.8thlight.com/articles/2010/12/6/clojure-libs-and-namespaces-require-use-import-and-ns

17:00 Pupeno: technomancy: what daemons does it need? the app itself (I presume there's nothing like Phusion Passanger, yet); anything else?

17:00 technomancy: Pupeno: the other part is the scp load balancer

17:01 hang on

17:01 Pupeno: technomancy: ah… sounds interesting and a pain in the ass.

17:01 technomancy: http://p.hagelb.org/clojars-deploy.html

17:01 wtf__ftw: amalloy, removing the extra parens gives this error instead: "java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol"

17:01 technomancy: Pupeno: only a pain if you set everything up manually =)

17:01 wtf__ftw: 4 hours of debugging tells me it comes from the ns macro form

17:01 technomancy: if you use vagrant it gets set up for you

17:02 amalloy: paste your current "fixed but still broken" version

17:05 Pupeno: technomancy: I see.

17:05 wtf__ftw: amalloy, here's the new paste: http://pastebin.com/W2xEPyVT

17:06 amalloy: looks good to me. i think your error is elsewhere now

17:06 technomancy: Pupeno: if you can do scp uploads on your main machine you probably don't need to worry about it, I'm just explaining why this method is what I'd recommend by default for folks getting started.

17:07 Pupeno: technomancy: I understand.

17:07 wtf__ftw: amalloy, looks like I'm still getting the ISeq from Symbol error from above

17:07 Pupeno: technomancy: can I ask you few more questions about it?

17:08 technomancy: Pupeno: I'm about to get on the phone so I probably won't be too responsive, but _ato might be online soon, so it doesn't hurt to ask.

17:08 amalloy: your namespace form is fine. you're either using stale versions of that code, or your problem is elsewhere

17:08 Pupeno: Ok.

17:09 So you upload these two files… then what happens? There's a process in clojars that is polling for files or something like that and adds them to the database?

17:10 wtf__ftw: amalloy, I've put up an updated paste: http://pastebin.com/8t52SPQL

17:10 technomancy: Pupeno: it hooks up to nailgun which connects to a listener directly in the main web app process.

17:10 hiredman: no, when you upload the files they are handed off to the clojure

17:10 clojars

17:10 wtf__ftw: it's the only other file I have my leiningen project

17:10 hiredman: (what technomancy said)

17:11 amalloy: (a) your first two ns forms are still wrong, (b) gen-class may or may not be right, i don't use that

17:11 hiredman: clojars actually runs as a 'scp-shell' sort of thing and recieves the files directly

17:11 (which is pretty nuts)

17:11 _ato: but it works :)

17:11 wtf__ftw: amalloy, the (a) part: which part looks wrong?

17:11 _ato: I am liking your rewrite of the scp code though

17:11 Pupeno: hiredman: clojars is set as a scp-shell for a user?

17:12 as shell.

17:12 hiredman: Pupeno: yes (but ask _ato)

17:12 technomancy: it does work surprisingly well =)

17:12 amalloy: wtf__ftw: everything. your paste at http://pastebin.com/W2xEPyVT is perfect, but your latest at http://pastebin.com/8t52SPQL goes back to the pre-fix version

17:12 dnolen: wtf__ftw: missing a closing paren on line 2

17:12 _ato: Pupeno: nailgun is, which connects to the clojars process

17:12 hiredman: _ato: nuts and ingenious

17:12 wtf__ftw: ah, hold on, Pastebin used the old version

17:12 ... new version in a second

17:12 Pupeno: I don't know nailgun, are you talking about http://www.martiansoftware.com/nailgun/ ?

17:13 _ato: yep

17:13 Pupeno: Is there a way to trigger the upload process without having a user and so on?

17:13 _ato: so there's a small C client which connects via socket to the JVM process and pipes its stdin/stdout over that socket

17:13 not really

17:13 wtf__ftw: corrected paste: http://pastebin.com/Sb2c2rB6

17:14 amalloy: everything (except, again, the gen-class which i'm not going to try to figure out) looks perfect there

17:15 wtf__ftw: that's helpful I guess, thanks amalloy

17:15 and dnolen

17:15 dnolen: wtf__ftw: what dev env r u using?

17:16 wtf__ftw: lein

17:16 dnolen: wtf__ftw: lein and a regular text editor? vim? emacs?

17:16 wtf__ftw: lein + emacs

17:16 dnolen: wtf__ftw: SLIME ?

17:17 wtf__ftw: I have swank turned off

17:17 * Pupeno is giving La Clojure a chance.

17:17 wtf__ftw: (slime on my system is already configured for Common Lisp development under sbcl)

17:18 dnolen: wtf__ftw: debugging this kind of stuff is a bit painful with SLIME since you can't test individual forms.

17:18 s/with/without

17:18 lazybot: <dnolen> wtf__ftw: debugging this kind of stuff is a bit painful without SLIME since you can't test individual forms.

17:18 wtf__ftw: I hear that

17:19 Pupeno: wtf__ftw: clojure-jack-in seems to be able to run SLIME with Clojure without changing your configuration… but don't take my word for it.


17:20 wtf__ftw: hmm

17:20 I'll check that out

17:37 jowag: Hi, how do I get the type of object in ClojureScript? I want to test if a specific object was created with my specific deftype or not

17:45 wtf__ftw: thanks for the help guys, I need to get going, but the newer version of clojure-mode w/swank should help

17:47 jowag: nevermind, found it, it is with function called "instance?"

17:49 scgilardi: jowag: did the function type not work?

17:49 (type my-object)

17:50 dnolen: scgilardi: ClojureScript doesn't have type yet. JavaScript doesn't it make it easy to support either.

17:50 scgilardi: ok, thanks

17:54 krl: hmm. can you have slime display errors that occur in other threads than the main one?

17:57 triyo: I came across this post that shows that in CLJS, one can compile third_party libraries. This post shows the details: http://groups.google.com/group/clojure/browse_thread/thread/f45efc0ead9c56b0/5eaa69d8f6d18711?lnk=gst&q=clojurescript+src#5eaa69d8f6d18711

17:58 I get an error when calling the third part library though after running it through the compiler.

17:58 Uncaught ReferenceError: Showdown is not defined

17:59 Meaning, it doesn't even find the top-level function of the library called Showdown

17:59 anyone tried to compile third-party libraries?

18:01 ordnungswidrig: hi all

18:18 gstamp: is there any easy way to clear out a namespace? At the moment I'm restarting swank every time I need to do this.

18:24 Frozenlock: If you're using emacs: M-x slime-repl-clear-buffer

18:26 amalloy: uh, that's not what he wants

18:27 you want ##(doc ns-unmap) or ##(doc remove-ns)

18:27 lazybot: (doc ns-unmap) java.lang.SecurityException: You tripped the alarm! ns-unmap is bad!

18:27 (doc remove-ns) ⇒ "([sym]); Removes the namespace named by the symbol. Use with caution. Cannot be used to remove the clojure namespace."

18:28 Frozenlock: Oh, my apologies

18:40 amalloy: anyone know if clojure.contrib.def has been migrated to a non-monolithic contrib?

18:43 technomancy: amalloy: pretty sure it hasn't

19:07 lynaghk: Hi everyone, I'm just getting into ClojureScript and I have a few questions about JavaScript interop

19:08 In particular, how can I make native JS objects. Something like (range 3) -> [0, 1, 2]

19:09 printing (range 3) to the JS console gives me an object of type cljs.core.LazySeq.

19:11 (.array (vec (range 3))) will work, but is that the recommended way to interop?

19:57 Raynes: Are there plans to implement letfn in ClojureScript?

20:03 gstamp: amalloy: thanks (belated)

20:42 Nikelandjelo: Hi. I'm trying to use new Path class from jdk7. TO get path there are 2 methods get(URI uri), get(String first, String... parts). How can I call second method, not first one? It throws exception, that cannot convert STring to URI

20:43 hiredman: java varargs are arrays

20:47 Nikelandjelo: hiredman: Thanks

20:56 mjreed: java.lang.IllegalStateException: var: #'clojure.string/replace-by is not public

20:56 ? bogus message caused by some other problem, or was that function deprecated/replaced in 1.2.1?

21:11 ah, I was looking at contrib, not the promoted api. nm.

21:47 currymj: I'm trying to get Aquamacs set up for clojure development. I've installed leiningen, the emacs starter kit, and all the relevant packages, but M-x clojure-jack-in doesn't do anything, nor does M-x slime. I'm pretty lost. Can someone help?

21:48 Scriptor: currymj: have you tried doing lein swank from the project's directory?

21:48 (from a shell)

21:51 currymj: Scriptor: i have, and it seems to start the swank server, but i have no idea what to do from there. emacs is sort of alien territory for me.

21:51 Scriptor: currymj: try M-x slime-connec

21:52 *slime-connect

21:52 amalloy: Scriptor: aw, slime-connec would work fine. or slime-con, even

21:52 currymj: Scriptor: it says "no match". is there another package i have to install besides clojure-mode?

21:56 Scriptor: currymj: just to make sure, do M-x package-list-packages and scroll to the bottom where it should list installec packages

21:56 currymj: i have clojure-mode 1.10.0 and paredit 22 installed

21:58 Scriptor: currymj: what shows up when you do M-x clo and then hit tab?

21:59 amalloy: damn, so it just pretends you hit tab and runs the auto-completed command?

22:00 amalloy: Scriptor: yes

22:02 rufius: Is it ever appropriate to use a map to hold a set of parameters for a function rather than relying on just arguments. I've got a funciton that takes about 6-7 arguments but it is kind of ugly to call outright. Is there any reason I shouldn't use a map with all the values contained in that and pass it as the sole argument?

22:02 currymj: Scriptor: http://pastebin.com/K7BmG8Tk

22:02 amalloy: Scriptor: somewhere there's a package that does fuzzy completion of M-x. super-neat, but i don't have it installed at the moment

22:02 rufius: please, do use a map

22:03 Scriptor: currymj: hmm, can't say to be honest, though I vaguely remember having the same problem

22:03 try restarting emacs if you haven't already?

22:03 also, when you open a clojure file, do you still get syntax highlighting?

22:03 rufius: amalloy: good to hear/read :). I'm just learning clojure but am still trying to gather what are considered "best practices" or idiomatic styles of writing code

22:06 currymj: Scriptor: just restarted emacs, same problem, i have "lein swank" going in a separate window, and i get syntax highlighting/indentation just from opening a .clj file. i may just compile regular GNU emacs from source and see if that fixes the problem, but rich hickey uses aquamacs so i feel like it should work.

22:07 Scriptor: currymj: you can try carbon emacs too

22:08 it's supposed to keep the same bindings, while aquamacs makes them a little more beginner-friendly

22:11 hiredman: aquamacs is not to be recomended

22:11 http://emacsformacosx.com/builds

22:12 get one of those

22:12 (better yet build it yourself and apply the fullscreen patch, but that can wait)

22:22 currymj: okay, so with non-fancy emacs it seems to be functioning. i can launch a swank server using lein and connect. is there something i should put in my .emacs that might make this simpler? what do other emacs users do?

22:26 also, how do i open a repl? :/

22:27 Scriptor: currymj: slime-connect should be the repl itself

22:28 also, I think most now just use clojure-jack-in

22:36 currymj: does swank-clojure look for lein in a specific directory? mine is installed in /usr/local/bin and i'm wondering if i need a symlink. the problem appears to be that emacs can't find the lein command when it tries to invoke it.

22:37 hiredman: ah, that is an issue with osx, it doesn't start .apps with the proper env unless you do some findle with xml

22:38 so emacs won't have the right PATH

22:39 tomoj: I have a 391mb jar which is part of an unmavenized project. I suppose I should _not_ push this to clojars.. :)?

22:42 currymj: hiredman: do you know how i do this? specifically in Lion, because the advice online seems to now be out of date

22:42 hiredman: tomoj: clojars won't accept anything over 19mb

22:43 currymj: (setenv "PATH" …)

22:43 tomoj: ah, that is reasonable

22:46 currymj: "Connected. Hack and be merry!"

22:46 thanks, everyone, for all your help

23:31 leonid: hah

23:35 icey: Does this look like a stylistically correct way to do tests? https://gist.github.com/1119554

23:35 Or should I wrap all the tests in an "and" with a single "is" assertion?

23:36 amalloy: icey: you want lots of is's, so that when one fails you can tell which

23:36 icey: amalloy: that's what I figured, but I wanted to make sure. Thanks!

23:36 amalloy: but there's also (are) for very repetitive tests like that

23:36 icey: amalloy: reading up on (are) now, thanks!

23:37 amalloy: (are [email] (vali/is-email? email) "foo@bar.com" "etc@whatever.co.uk")

23:37 icey: amalloy: sweet, that looks like exactly what i need

23:41 amalloy: oh yeah, that looks WAY better, thanks again (Here's what it looks like now https://gist.github.com/1119554)

23:59 grant__: maybe you should stop changing your name...

Logging service provided by n01se.net