#clojure log - Sep 15 2012

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

0:00 tomoj: updated second gist with a better example

0:00 (reduce-kv conj [] r) should not make sense, right?

0:00 oh well, it could

0:02 anyway, I again don't understand why rfn is there

0:02 Sgeo: I am seriously going to cry

0:04 tomoj: the only purpose for rfn I can imagine is reduce-kv, but ([ret k v] (f1 ret (f k v))) seems to violate reduce-kv's contract

0:11 Sgeo: Someone please explain to me in understandable language why algo.monads doesn't use Leiningen

1:04 Uh

1:05 Does Enclojure not support Leiningen, nor Clojure past 1.2?

1:06 Raynes: Enclojure is the least maintained of the Clojure environments.

1:06 I'd be surprised if it worked at all.

1:08 Sgeo: :(

1:08 Ok, so what's well-maintained that isn't Counterclockwise?

1:08 I'm done fighting with Eclipse

1:08 cark: emacs =P

1:09 Raynes: Light table, but it's extremely new and missing things like one-off editing.

1:09 Sgeo: one-off editing

1:09 ?

1:10 Raynes: As in you can't just pick a file on the filesystem and edit it.

1:10 cark: missing paredit too =(

1:10 Raynes: But yeah, Emacs, Vim, Light table...

1:10 amalloy: light table is well maintained? i don't think "maintained" is a good word for that

1:10 Raynes: cark: Yeah, I hope someone adds that to codemirror soon.

1:10 amalloy: I'm pretty sure it qualifies.

1:11 cark: i think lighttable isn't quite ready for prime-time

1:11 Raynes: It isn't, but I'm not sure paredit is the reason.

1:11 Paredit is something that has generally nothing to do with light table.

1:12 As a matter of fact, nothing editor-related does. All of that needs to be done in codemirror itself which is a separate project by a different person.

1:12 I wish he was more exuberant about that. LT isn't open source yet, so people don't think they can contribute when in fact they can contribute to one of the most important components right now.

1:13 cark: the two big ones are counterclockwise and emacs, emacs is the best of the two imo, and the skills you get with emacs are good for lots of other languages

1:19 Sgeo: codemirror?

1:20 There exists a language called Smarty.

2:27 sal: need help on slime-ritz, installed a new emacs 24 with clojure, swank, slime

2:28 swank and clojure mode working, but slime doesn't start

2:36 anybody on github, with slime-ritz emacs setup, which i can look at, thx

4:21 ro_st: technomancy: how do i resolve "target/stale/dependencies (No such file or directory)" on lein2 preview10?

4:22 sunkencityryleh: what's this # character that's needed to get the metadata? (meta #'pr-str) why not good enough with just a quote?

4:23 ro_st: nm. i'm a dumbass. permissions

4:23 tomoj: &'#'pr-str

4:23 lazybot: ⇒ (var pr-str)

4:24 sunkencityryleh: hm, so it's a var-quote

4:32 philandstuff: hello. I believe I've found a couple of bugs in PersistentQueue. I've emailed clojure-dev about them. I haven't had a response. Should I open JIRA tickets for them?

4:37 tomoj: the flowchart suggests that anyone can open an issue

4:38 the text below seems to suggest that you get feedback on clojure-dev before doing so. confusing

4:59 philandstuff: tomoj: yeah, that's how I feel

5:01 oh well, I've sent another email, trying to be clearer and asking direct questions about filing a bug

5:02 of course most of clojure/core will be asleep right now

5:02 clj_newb_2345: i know about code mirror2

5:02 however, I'm curious -- is there any editor written in clojurescript?

5:05 cark: a couple bugs in persistentqueue ?

5:12 kral: morning

5:14 philandstuff: cark: yes. I brought them up on clojure-dev

5:14 I filed one as http://dev.clojure.org/jira/browse/CLJ-1059

5:16 cark: oh i see

5:17 philandstuff: there's a couple others around PersistentQueue's hash fn, which doesn't match its = fn

5:18 nothing earth-shattering

5:18 cark: you got me worried for a second =P

5:20 dfd: I'm wondering, is there anyone here living in Asia?

5:22 luxbock: I'm staying in Bangkok

5:22 why?

5:22 clojurebot: luxbock: because you can't handle the truth!

5:22 dfd: haha

5:22 luxbock: :D

5:23 dfd: luxbock: just curious. I live in Japan, and I would like to learn more about whether there is much of a Clojure community here, or anywhere else in this (large) region

5:23 I know there are some Japanese folks using Clojure, I'm also curious if they hang out on the English-speaking channel.

5:23 and of course anyone else.

5:23 luxbock: hmm, no clue

5:23 dfd: (in Asia)

5:24 yeah, just sorta throwing it out there. Anyways, enjoy Thailand. Love that place. ;-)

5:42 votz: If I have a namespace without :gen-class, built and packed with leiningen's uberjar, how can one invoke a method, like foo, from the command line with java? java -cp test.jar [...]?

5:43 Along the lines of http://pastie.org/private/cdtvivjaqtu9zatlmhlha

6:09 gfredericks: votz: from a jar you have to have a class to run; you can run clojure.main and get a repl...if there's a built in clojure way to call a specific jar I'd be interested

6:09 s/jar/var/

6:09 ro_st: anyone using datomic here can answer a stupid question for me?

6:10 how do i query out the timestamps for data?

6:13 votz: gfredericks: Once in the clojure.main REPL, what's the best way to invoke foo of (ns test.core)?

6:15 The namespace 'test' is not listed in (all-ns).

6:15 tomoj: java -cp test.jar clojure.main -e "(use 'test.core) (foo)"

6:15 gfredericks: you'd have to require it first

6:15 tomoj: I think

6:16 gfredericks: or use it as tomoj suggests with his commandline-args version I was asking for

6:16 hiredman: https://gist.github.com/3422228

6:17 votz: tomoj: Bingo. That appears to work.

6:19 michaelr`: hello

6:19 votz: Thank you for your help and input gfredericks and tomoj.

6:26 Sgeo: I guess I should try that instead of fighting with leiningen

6:26 Are there any advantages to lein repl over using clojure.... hmm

6:26 That looks like it requires clojure directly in the cp?

6:27 Where does Leiningen install clojure.jar?

6:30 gfredericks: Sgeo: I'd say not using lein is only worth it if you've made an uberjar

6:31 Sgeo: gfredericks, how about testing modifications to a library that doesn't use Leiningen?

6:31 Or how about playing with a .jar generated with JNAerator

6:32 xeqi: Sgeo: leiningen uses clojure from your ~/.m2/repository

6:32 gfredericks: try `lein classpath`?

6:33 xeqi: as far as advantages, not having to manage the classpath yourself and manually download dependencies

6:36 Sgeo: GUESS WHAT I JUST LEARNED

6:37 THERE IS A project.clj IN ALGO.MONADS

6:37 Oh, wait, n/m

6:37 * gfredericks was going to guess "computers"

6:50 Sgeo: https://www.refheap.com/paste/5090

6:51 scottj: Sgeo: Not sure if this is what you're wondering, but you can use algo.monads from a lein project, you just need to pull the version out of pom.xml and make sure you lein pulls from the repo algo.monads is deployed to

6:51 Sgeo: (Note that this doesn't use the publically available m-lift-fn, but one that's modified to be curried by default)

6:52 I don't entirely understand why the first and second don't match, but the second and third matching is very good

6:52 Does this count as testing?

6:53 Getting rid of the m-result makes the ( ) around individual items go away

6:54 I think domonad is putting an implicit m-result there.

6:54 Which is completely and utterly inappropriate, I think

7:00 $mail jimduey I dare you to try to write m-join using domonad.

7:00 lazybot: Message saved.

7:00 Sgeo: $mail jimduey Hint: domonad appears to include an m-result implicitly.

7:00 lazybot: Message saved.

7:07 philandstuff: Sgeo: I agree that the m-result is entirely inappropriate. Probably too late to remove, but you should be able to write your own domonad* which does what you want.

7:07 * ro_st gets Datomic, suddenly

7:09 dfd: Clojure folks, I'm a Perl and Ruby person from way back, so whenever I start thinking about manipulating strings I will do stuff like chain regexp expressions together. But I just wrote some Clojure that feels super-un-Clojure-like: https://gist.github.com/3727361

7:09 What is a idiomatic way to do this in Clojure?

7:09 ro_st: i'd start with the threading macro

7:10 http://clojuredocs.org/clojure_core/clojure.core/-%3E

7:10 dfd: ro_st: like, pass the results to successive clojure.string/replace calls? That would be nicer, yeah

7:10 ro_st: nothing wrong with regexen, imho

7:11 Sgeo: Am I allowed to call the author of algo.monads incompetent?

7:12 ro_st: this is nice and clear: https://www.refheap.com/paste/5091

7:12 dfd: ro_st: thanks, that's really helpful. I'm still not used to thinking about -> automatically, but it is such a useful macro.

7:13 ro_st: i love how readable it makes a tangle

7:13 and it reduces the amount of text through the auto arg passing

7:13 dfd: yeah, seriously.

7:13 ro_st: it reads -> about _this_: transform 1, then transform 2.

7:13 dfd: good stuff. Thanks!

7:14 ro_st: cool

7:17 philandstuff: Sgeo: if you want to make it better, submit patches

7:27 Sgeo: https://github.com/Sgeo/algo.monads/commit/cd8cec109ed2df6fdf81a2566f944b1139f6a194

7:28 ro_st: Sgeo: what is this wizardry?

7:28 go slow. i'm not a neckbeard.

7:28 Sgeo: ro_st, do you know anything about monads?

7:29 Oh, the 15 new lines in the test are just a copy/paste of another test

7:30 ro_st: i know only that they're a functional pattern for injecting different kinds of work between the work passed to a monad

7:30 eg, nil checking or whatever

7:30 never used one. haven't tried yet

7:31 what does the sequence monad do?

7:31 Sgeo: The sequence monad is sort of non-determinism

7:31 ro_st: actually, where would you use this stuff?

7:31 Sgeo: '(1 2 3 4 5) can be considered to represent either the value 1 or the value 2 or the value 3 or the value 4 or the value 5

7:32 (domonad sequence-m [a '(1 2 3 4 5) b '(2 3 4 5 6)] (+ a b))

7:32 That addition can be said to be adding, conceptually, the possibilities of a and the possibilities of b

7:33 The end result is a sequence that represents the addition of each possible a and b

7:33 ro_st: so, permutations

7:33 Sgeo: Yes.

7:33 Note that this is specific to the sequence monad. Different monads can do different things, but can be generally manipulated with the same tools

7:34 domonad will work with other things too, for instance.

7:34 ro_st: i've heard of the error and maybe monads

7:34 Sgeo: What m-lift and m-lift-fn do is take a monad-unaware function and convert it into one that takes monadic values

7:35 (m-lift-fn +) knows how to do the permutations thing, so to speak

7:36 ro_st: it wraps it in the right sort of machinery for domonad to work with

7:36 Sgeo: (Note that m-lift-fn does not exist in vanilla clojure.algo.monads, it's a function I wrote. c.a.m uses a macro m-lift instead)

7:36 domonad itself isn't the machinery

7:36 It's just a pretty way of writing code that uses this sort of thing

7:36 ro_st: ah

7:37 what need produced these monads?

7:37 what field are they being used in?

7:37 trying to understand the why of it

7:37 Sgeo: Well, Haskell uses them for I/O

7:37 ro_st: oh, right

7:37 Sgeo: They provide a way to describe things being done in a certain order

7:38 They're also convenient for doing state

7:38 ro_st: that's right because haskell doesn't guarantee an execution order

7:39 Sgeo: The State monad wraps up the pattern of returning two values, one representing a global state, and feeding that global state into the next thing, in a convenient to use way

7:41 There's also a library using them to manage resources that should be closed in a timely fashion

7:41 ro_st: a with-open style thing

7:42 Sgeo: I'm... not sure how to describe it. It's a bit more flexible than with-open

7:42 ro_st: that's ok. don't hurt yourself trying. i'm merely curious

7:42 Sgeo: I'd say it's more like a macro in which you could register actions to be done when the code in the macro is done executing

7:43 Such registered code will always be called exactly once.

7:43 ro_st: ah, kinda like try's finally

7:43 Sgeo: Hmm. Yes, excpet without forcing them to be written in one part of the macro

7:44 But a major point is that, with all of these things, there are functions that apply to all of them

7:45 m-lift-fn, m-join, there's a map-like function (although that's another thing I'm mad about. All monads support that, but there's more than just monads that support it)

7:45 ro_st: what does m-join do?

7:45 does it relate to fork/join?

7:46 Sgeo: If you have a monadic value in a monadic value, it unwraps it one level

7:46 ro_st: i heard rhickey mention it in an interview

7:46 Sgeo: ,(apply concat '((1 2 3) (4 5 6)))

7:46 clojurebot: (1 2 3 4 5 ...)

7:46 ro_st: oh right, so probably not

7:46 Sgeo: So, m-join for the sequence monad is apply concat

7:48 In fact, if you can define m-join, you have a monad.

7:48 Although the typical definition of monads uses a bit more difficult way to define them

7:49 ro_st: so a monad is what to do with result from operation a when giving it to operation b

7:50 Sgeo: It's... not quite that simple

7:50 I think

7:50 ro_st: -grin-

7:51 Sgeo: There are two operations you need to define (If you define them, m-join can be defined in terms of them, and if you define m-join, these can be defined in terms of m-join)

7:51 m-bind and m-result

7:51 m-result simply wraps up its argument in ... a monadic value, so to speak

7:51 ,(list 5)

7:51 clojurebot: (5)

7:51 Sgeo: m-result for the sequence monad might simply be list, for example.

7:52 ro_st: gotcha

7:53 Sgeo: m-bind takes two arguments. A monadic value, such as, in the case of the sequence monad, a sequence. And a function, that takes an argument that isn't a monadic value, and gives a result that is

7:54 (Note that a function that doesn't know how to give a monadic value can easily be turned into one that does, by doing m-result on its result)

7:56 For example, the sequence monad's m-bind will takes the monadic value argument (a sequence), and run the function that it's given once for each value in the sequence. It will then take all the results, and concatenate them together

7:56 ro_st: ah so bind is the workhorse

7:57 Sgeo: Yes

7:57 ro_st: result prepares individual results for the workhorse to use for each cycle, and join prepares the final result for return to the caller

7:57 let me guess: it's not that simple? -grin-

7:59 Sgeo: Well, you don't need to use result, although it's convenient (and it does need to be defined). And join is ... more of an alternative workhorse, that might be easier to define in some cases, and might be convenient to use in some cases

8:00 ro_st: i guess each monad has slightly different emphases

8:00 putting the work in different places

8:00 Sgeo: More that they do different work

8:00 Different definitions of m-bind and m-return

8:00 ro_st: could you define a nothing monad that has all the parts but leave the inputs unaffected?

8:01 Sgeo: Yes

8:01 m-bind would take an ordinary value and a function, and apply the function to the value

8:01 m-return would just be identity

8:01 ro_st: oh i think i see: you could use different combinations of different binds and returns and joins?

8:02 Sgeo: No. bind and return are supposed to be defined in one way for one monad, and a different way for a different monad.

8:02 At least that's how it works in Haskell.

8:02 ro_st: ok so the monad's definition is in the bind and the return

8:02 Sgeo: ro_st, yes, exactly.

8:02 ro_st: gotcha

8:03 very interesting. it's on my list

8:03 along with several billion other things

8:03 -sigh-

8:04 Sgeo: Hmm. Was I saying return or result? Because return is the Haskell term, but clojure.algo.monads says m-result

8:04 ro_st: i inferred that :-)

8:05 time to go. happy hacking, Sgeo

8:05 Sgeo: Thanks. Bye.

8:10 $mail jimduey I take back my challenge. It's possible, just not nice like in Haskell.

8:10 lazybot: Message saved.

8:33 kjellski: what is the best way to get the OOP nightmare out of my head? ^^ this seems to "block" my functional thinking a lot ...

8:33 hammer?

8:34 wmealing_: use a different editor

8:34 with a different color scheme

8:34 on a different computer

8:34 in a different room

8:34 worked for me

8:35 i intentionally work from the data structures backwards too

8:35 but i'm an average clojure programmer

8:35 not great by any means

8:38 Sgeo: Haskell would give you a straightjacket

8:38 kjellski: wmealing_: thanks, that is a great idea…

8:39 wmealing_: i found it worked.. i do my clojure outside, and my C in the office.

8:40 let me know how it goes for you

8:40 kjellski: wmealing_: I'll let you know :) thanks

8:50 antares_: kjellski: I suggest that you model a few basic problems with protocols

8:52 Sgeo: Protocols gross me out

8:52 Multimethods seem more versitile

8:52 And protocols vs multimethods is a leaky distinction

8:54 kjellski: antares_: Sgeo: with enough time, I'll try both :)

8:54 antares_: kjellski: protocols will probably be very straightforward to you, then you can try more ad-hoc polymorphism with multimethods. As for managing state, see some game tutorials out there.

9:24 mindbender1: sophisticated type systems vs simpler type systems

9:25 clojure=*simpler* type system

10:12 jro_: if I want to define a configuration file, is following way dangerous somehow: (def properties (if (file-exists? properties-file) (eval (read-string (slurp properties-file))) default-properties))

10:17 sunkencityryleh: So when I launch my project with "lein repl" and do macroexpand-1 on my macro I get this garbage printout "#<core$if_method$fn__304…" what am I doing wrong?

10:17 uh, so I needed to quote it

10:18 I

10:53 gfredericks: sunkencityryleh: yeah :) gotta return code, not functions

11:39 casion: where can I find information on writing performant clojure code?

11:42 antares_: casion: performance is very workload specific. Profile first. Java Performance book by Charlie Hunt is a great book on the subject.

11:43 casion: antares_: I have that on my reading list, however I was looking for more clojure specific topics

11:44 antares_: avoid reflection warnings, use protocols over multimethods where possible, use transients in critical places

11:44 there are no other hard and fast rules for Clojure

11:44 dhofstet: casion: there is chapter about performance in "the joy of clojure"

11:44 casion: dhofstet: oh, I guess I haven't got there yet

11:46 hmm, what would be an example of a time where you would use a multimethod over a protocol?

11:53 antares_: when you dispatch on the type of the first argument

11:53 protocols cannot do anything else

11:54 but they are more efficient, single dispatch vs double dispatch

11:54 no7hing: are there any benchmarks about this out there?

11:55 on how much faster protocols really are? as in orders of magnitude(s)

12:12 antares_: no7hing: unlikely that it is orders of magnitude but in a tight loop 1 method invokation vs 2 matters. Plus multimethods are synchronized in 1.4.

12:15 no7hing: synchronized e.g. when i add new methods to it?

12:18 polycosm: (In emacs) Hello, can someone explain to me how to import functions from an opened file to nrepl ? (C-c C-k does nothing).

12:19 jam`: (use 'your-ns)

12:20 or require or whatever

12:20 antares_: no7hing: as well as during dispatch, see https://github.com/clojure/clojure/commit/83ebf814d5d6663c49c1b2d0d076b57638bff673

12:20 no7hing: oh noes

12:20 jam`: or in-ns to your workspace

12:20 no7hing: a huge contention point just built up in front of me

12:20 jam`: I mean namespace

12:22 is there a function like split-by in the example? (split-by even? (range 10))

12:22 => [(8 6 4 2 0) (9 7 5 3 1)]

12:23 polycosm: hmm jam` I'm trying but I can't seem to figure it out (about in-ns) how do you turn it on ?

12:23 Scriptor: ,(doc group-by)

12:23 clojurebot: "([f coll]); Returns a map of the elements of coll keyed by the result of f on each element. The value at each key will be a vector of the corresponding elements, in the order they appeared in coll."

12:24 Scriptor: jam`: could probably just call vals on that ^

12:24 jam`: cheers Scriptor

12:25 polycosm: if you have, for example, "my-core" namespace file opened in emacs then you can do (in-ns 'my-core) in nrepl

12:26 polycosm: then after you do c-c c-k in that file the lastest compild version will be available in nrepl

12:26 polycosm: oh thank you very much

12:26 jam`: wlm

12:27 or if you're in another ns you can do (use 'my-core)

12:27 to import its functions into the ns you're playing with in nrepl

12:30 polycosm: my repl doesn't know "use" though

12:31 jam`: hmm, strange

12:31 mine does:

12:31 user> use

12:31 #<core$use clojure.core$use@203da423>

12:32 polycosm: oh it's because I was in a ns I erased, my bad

12:32 jam`: ah, ok

12:46 antares_: no7hing: the RW lock implementation in master should be pretty good

12:47 no7hing: i already made a mental note to try it out ;)

12:47 trying to get https://github.com/davidsantiago/multifn-perf running, but no success

12:49 in my scenario 16-32 threads would try to get to the multimethods

12:49 which equals a bloody massacre

12:49 to

13:40 hfaafb: how should i find the largest item in a set that meets a certain condition

13:43 max-key seems right...

14:10 hyPiRion: hfaafb: usually, (apply max-key ...) is the way to go

14:10 hfaafb: ahh yeah just discovering that now ;)

14:13 werbitt: Hi, I'm trying to write a function that can take zero or more args but I'm having issues when I use it with zero args. Here's a gist: https://gist.github.com/3729077 . I appreciate any help.

14:22 wjc: Hi

14:23 I'm trying to use fetch with noir

14:23 I added fetch "0.1.0-SNAPSHOT" to project.clj

14:24 when I try to use fetch's remotes, I get a js error: POST http://localhost:8080/pinotremotecall 404 (Not Found)

14:25 megamind1: Oh..

14:25 wjc: after cloning fetch from github, I see no reference to pinot

14:25 megamind1: way many ppl than #Lisp

14:26 wjc: do I have the right version? fetch 0.1.0-SNAPSHOT? there's only two other alpha versions after doing a lein searc

14:26 *search

14:28 werbitt: your argument declarations are correct

14:29 but at the end, you wrapped ms, a vector: (ms), so clojure tries to execute your vector

14:30 werbitt: oh, i see, cool, thanks a lot

14:30 wjc: no problem

14:36 megamind1: anyone tried vsClojure extension ?

14:36 xeqi: wjc: I think -alpha2 is the latest

14:37 wjc: I tried it too, I still get the pinot error

14:38 I'm using noir 1.3.0-beta3, is that correct?

14:38 xeqi: I've gotten it to work with versions in https://github.com/xeqi/friend-fetch-example/blob/master/project.clj

14:39 I don't know much about the difference in the noir betas

14:40 wjc: just to make sure, you did remove the js file and recompile?

14:40 wjc: uh, good call

14:43 nope, same thing even with noir beta8

14:49 Xtreme: Hello

14:49 wjc: removing .lein-cljsbuild-compiler-0 did the trick

14:51 xeqi: strange, but glad its working for you now

14:51 Xtreme: megamind1, ooh, lol

14:52 wjc: yup, thanks

14:52 megamind1: yeah, that's it. Xtreme

15:04 Xtreme: guys is there any ide for clojure?

15:04 megamind1: a lot out there

15:04 hfaafb: how does #clojure feel about light table

15:04 (i'm new to the language and community)

15:05 Xtreme: megamind1, anyone whihc you prefer?

15:07 megamind1: since your work concern Java , I suggest netbean or eclipse for intelliJ

15:07 maybe easily to dig in code

15:09 Actually, I'm new to Clojure also. I'm just finding the most comfortable way to work with it :)

15:10 xeqi: in general the order of good clojure integration is emacs, eclipse w/ counterclockwise, vim w/ lein-tarsier, then a large gap before any others

15:11 Xtreme: and tutorials? nice set?

15:13 polycosm: Xtreme, try 4clojure.com I'm learning clojure through it right now, I find it really good

15:13 xeqi: yeah, 4clojure.com has a good set of problems that get harder over time

15:13 clojurebook.com is the recommended book if you like those

15:16 akhudek: xeqi: Intellij + La Clojure is also very nice.

15:16 Sgeo: o.O I learned something new today

15:17 jimduey's deftype for a Maybe monadic value stores the value in a closure for deref, and nowhere else

15:18 Oh woah it's horribly broken

15:18 The person who I pointed to it was right, I was wrong

15:19 xeqi: akhudek: do you know if it can use a project.clj or nrepl?

15:19 Sgeo: $mail jimduey You got Maybe wrong about as badly as algo.monads does. In fact, I'm not sure if it's even a monad, the way you (and algo.monads) describe it.

15:19 lazybot: Message saved.

15:20 akhudek: xeqi:

15:20 it's not that good sadly

15:21 though there is a lein plugin for intellij that I don't use

15:32 Sgeo: Quick question: If someone uses a symbol like ::blah, is that symbol considered private, in some sense?

15:33 xeqi: not really, its just a way to namespace and avoid collisions

15:33 &::blah

15:33 lazybot: ⇒ :clojure.core/blah

15:33 xeqi: &:blah

15:33 lazybot: ⇒ :blah

15:33 Sgeo: I'm wondering if I should consider ::nothing in my analysis of whether jimduey's maybe breaks the monad laws

15:34 If it's "private", so to speak, it would make sense if I didn't

15:34 hyPiRion: well

15:34 ,::foo

15:34 clojurebot: :sandbox/foo

15:34 Sgeo: (If I do consider it, it's trivially broken)

15:34 hyPiRion: ,(= ::foo :sandbox/foo)

15:34 clojurebot: true

15:35 Sgeo: So to give his library a fighting chance at acceptability..

15:35 * Sgeo decides to first consider algo.monads, it may be easier

15:36 Sgeo: algo.monads's maybe-m trivially breaks the monad laws.

15:36 Next contestant.

15:45 $mail jimduey I take that back, I think yours works, as long as users cannot themselves construct ::nothing. algo.monads's maybe-m trivially breaks the monad laws, though

15:45 lazybot: Message saved.

15:47 mwcampbell: I noticed that leiningen 2 places a file called "repl-port" in the current directory when I run "lein repl". Is this a feature? My guess is that it was a temporary thing for debugging that was mistakenly left in.

15:48 hyPiRion: mwcampbell: You're right.

15:48 Man, they exist probably in every folder on my computer.

15:59 technomancy: mwcampbell: it should be fixed in the latest version

16:01 akhudek: is anyone here familiar with shoreleave and it's csrf protection?

16:01 it seems to look for the anti-forgery token in a cookie

16:01 but I don't see any corresponding server side functionality to actually set the cookie

16:04 Sgeo: Wheee http://dev.clojure.org/jira/browse/ALGOM-7

16:11 megamind: hey yo

16:12 Can Clojure on Emacs auto discover available methods/property in imported Java library ?

16:21 akhudek: oh, wow

16:21 ok that was really confusing

16:21 shoreleave depends on a "fork" of ring-anti-forgery that does cookies

16:23 yet it links to the main project

16:24 or nevermind, it is just outdated and depends on an old anti-forgery

16:35 augustl: is it good or bad practice to have run-time type checks and throw exceptions if you pass, say, a vector instead of a map?

16:36 akhudek: augustl: you should use pre and post conditions for that

16:36 http://blog.fogus.me/2009/12/21/clojures-pre-and-post/

16:36 augustl: I see

16:37 going to make some functions that take specific Java types as arguments, makes sense to check for correct types I think.

16:37 amalloy: augustl: meh. you can do that if you want. but having every function covered with typechecks is lame; i don't recommend doing it except for the outermost layer

16:38 augustl: amalloy: I'm only thinking of doing it for my public API

16:38 akhudek: amalloy: I take it there is a performance hit with these checks too

16:38 amalloy: *shrug* of course

16:38 akhudek: is there a way of disabling them, say when running in production?

16:39 amalloy: but so what? if typechecks are your bottleneck your program sucks

16:39 TimMc: ...

16:39 Sgeo: amalloy, hey, did you see above ranting?

16:39 augustl: I'm making a ring middleware, so I'll only do the type checks when creating the handler function ;)

16:40 akhudek: amalloy: not always the case

16:40 amalloy: Sgeo: yes, but i'm not interested

16:41 akhudek: plus I use pre conditions for more then type checks at times

16:45 megamind: Can Clojure on Emacs auto discover available methods/property in imported Java library ? anyone ?

16:46 hyPiRion: megamind: Er, I don't believe so. At least not yet.

16:47 megamind: thanks, just in-case that happen, I don't need to download Eclipse

16:52 akhudek: nice, you can disable pre and post via *assert*

16:57 augustl: akhudek: cool

16:58 megamind: Is there any extension that work well with Clojure CLR ?

16:58 * IDE extension

17:08 sunkencityryleh: I'm stuck at figuring out how I can get the metadata of a symbol that is passed into a function without having to write a macro.

17:09 (defmacro arglist [action] `(-> ~action var meta :arglists first)) works but surely it should not need to be a macro?

17:12 hyPiRion: sunkencityryleh: use (meta (resolve symbol))

17:12 sunkencityryleh: hyPiRion: thanks

17:12 hyPiRion: it requires that the symbol exists within the namespace, though.

17:16 amalloy: sunkencityryleh: if it's a function, then (f x) is not passing the symbol x into the function, it's passing the currently-bound value

17:16 you really cannot count on any metadata attached to a function

17:18 sunkencityryleh: hm ok

17:22 I guess the macro way is the way to go then

17:22 amalloy: more likely you should just not do whatever you're trying to do

17:26 sunkencityryleh: probably

17:29 hyPiRion: $findfn [0 1 2 3] [2 3 0 1]

17:29 sunkencityryleh: I'm trying to write a macro that I can use with compojure to (add-action foobar/show) that looks at foobar/show and sees that it takes the arguments param and user and generates (GET "/foobar" {param :param user :user} (foobar param user))

17:29 lazybot: []

17:30 hyPiRion: dangit, is there any idiomatic way of rotating a seq?

17:30 sunkencityryleh: seems tedious to have to pull out the requests for each action I want to define

17:30 pull out the arguments

17:30 routing for

17:30 amalloy: &(doc cycle)

17:30 lazybot: ⇒ "([coll]); Returns a lazy (infinite!) sequence of repetitions of the items in coll."

17:31 amalloy: &(doc drop) ; hyPiRion

17:31 lazybot: ⇒ "([n coll]); Returns a lazy sequence of all but the first n items in coll."

17:32 hyPiRion: ,(take 4 (drop 2 (cycle [0 1 2 3])))

17:32 clojurebot: (2 3 0 1)

17:32 hyPiRion: oh well.

17:32 ,(let [[a b] (split-at 2 [0 1 2 3])] (concat b a)) ; was a bit tedious.

17:32 clojurebot: (2 3 0 1)

17:34 no7hing: if i want to make sure that certain keys are in a map argument, is pre the way to go?

17:34 :pre

17:35 if yes, is it possible to check for multiple of them? {:pre [(:id x) (:name x)]} seems verbose

17:36 to sum it up ;) i'am looking for an idiomatic way to make sure i got all i expect before starting computations

17:36 hyPiRion: no7hing: I believe it is the way to go. You could use ##(every? #{:id :name} (keys {:id 1 :name "foo"}))

17:36 lazybot: ⇒ true

17:36 no7hing: uh nice

17:36 thanks

17:37 Sgeo: Isn't there something in swiss-arrows?

17:37 aperiodic: no7hing: i'd do {:pre [(map (partial contains? x) [:id :name ...]]}

17:37 no7hing: i'am trying to not shoot myself - yet :D

17:38 but i had a look at the lib and was intrigued

17:38 hyPiRion: no7hing: aperiodic's solution is better than mine, performance-wise.

17:38 akhudek: hyPiRion: that will only check that every key is valid, not that every valid key is present

17:38 aperiodic: no7hing: note that (contains? x key) and (key x) will return different things depending on if x actually contains key, but maps it to a nil value, versus doesn't contain key at all

17:39 no7hing: also there should be an outer (every? identity ...) around the map form in what i suggested

17:39 no7hing: ,(contains {:id 1} :id)

17:39 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: contains in this context, compiling:(NO_SOURCE_PATH:0)>

17:39 no7hing: whoops

17:39 aperiodic: ,(contains? {:id nil} :id)

17:39 clojurebot: true

17:39 no7hing: ,(contains? {:id 1} :id)

17:39 clojurebot: true

17:40 aperiodic: ,(boolean (:id {:id nil}))

17:40 clojurebot: false

17:40 no7hing: never thought i'd say that, but i miss skype's correct feature

17:40 hyPiRion: aperiodic: Why not just ##(every? #(contains? {:id 1 :name "foo"} %) [:id :name])

17:40 lazybot: ⇒ true

17:42 no7hing: i only need to check for the presence of keys

17:42 amalloy: hyPiRion: aperiodic's (map (partial contains?)) doesn't work anyway

17:43 aperiodic: drat, what did i screw up?

17:43 hyPiRion: amalloy: he said that "there should be an outer (every? identity ...) around the map form"

17:44 jkkramer: (defn has-keys? [m & ks] (every? #(contains? m %) ks)) … {:pre [(has-keys? arg :a :b :c)]}

17:44 hyPiRion: yeah, that's sweet.

17:44 amalloy: oh, i missed that

17:45 aperiodic: yeah, defining a function makes the discussion around whether you like maps & partials or anon function literals moot

17:45 (inc jkkramer)

17:45 lazybot: ⇒ 3

17:46 Sgeo: I like partials

17:46 >.>

17:46 Makes me miss Haskell a little less

17:46 hfaafb: ,(require clojure.set/map-invert)

17:46 clojurebot: #<CompilerException java.lang.RuntimeException: java.lang.ClassNotFoundException: clojure.set, compiling:(NO_SOURCE_PATH:0)>

17:47 hyPiRion: I like them in the sense that they are "pure to the eye". But they're slow :(

17:47 ,(require 'clojure.set)

17:47 clojurebot: nil

17:47 hfaafb: ahh so what is this apostrophe business

17:47 don't evaluate me just yet?

17:48 hyPiRion: hfaafb: yeah, it's a quote, for "just quote me, don't evaluate me"

17:48 Sgeo: It's more "don't evaluate me" period

17:48 ,(str '(1 2 3 4 5))

17:48 clojurebot: "(1 2 3 4 5)"

17:48 Sgeo: ,(str (1 2 3 4 5))

17:48 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

17:48 Sgeo: ,(str (quote (1 2 3 4 5))

17:48 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

17:49 Sgeo: ,(str (quote (1 2 3 4 5)))

17:49 clojurebot: "(1 2 3 4 5)"

17:49 Sgeo: ,('(1 2 3 4 5))

17:49 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn>

17:49 Sgeo: ,(identity '(1 2 3 4 5))

17:49 clojurebot: (1 2 3 4 5)

17:50 Sgeo: ,'(1 2 3 4 5)

17:50 clojurebot: (1 2 3 4 5)

17:50 Sgeo: Oh hey

17:50 aperiodic: hyPiRion: are partials slower than an anonymous function wrapper, then?

17:51 hyPiRion: &(time (reduce #(+ %1 %2) 0 (range 10000000)))

17:51 lazybot: ⇒ "Elapsed time: 2032.59323 msecs" 49999995000000

17:51 hyPiRion: &(time (reduce #(+ %1 %2) 0 (range 10000000)))

17:51 lazybot: ⇒ "Elapsed time: 1986.303416 msecs" 49999995000000

17:51 hyPiRion: &(time (reduce #(+ %1 %2) 0 (range 10000000)))

17:51 lazybot: ⇒ "Elapsed time: 1893.38111 msecs" 49999995000000

17:51 hyPiRion: &(time (reduce (partial +) 0 (range 10000000)))

17:51 lazybot: clojure.lang.ArityException: Wrong number of args (1) passed to: core$partial

17:51 hyPiRion: meh.

17:51 &(time (reduce (partial + 0) 0 (range 10000000)))

17:51 lazybot: Execution Timed Out!

17:52 aperiodic: apparently so

17:52 Sgeo: I just realized that I don't like that you need to pass more args to partial like that

17:52 (partial +) makes perfect sense, it's just +. It might seem useless, and I assume that's why it doesn't exist, but if you're making a macro to generate code, do you really want to have to detect that sort of thing?

17:53 casion: why would partial be faster? that doesn't make sense to me at all

17:53 aperiodic: i guess because more of the work for the anonymous function wrapper happens at compile time, whereas partial does it at runtime?

17:53 Raynes: Guys.

17:53 xeqi: %(time (apply + (range 10000000)))

17:53 &(time (apply + (range 10000000)))

17:53 Raynes: Please don't use lazybot or clojurebot for testing speeds.

17:53 lazybot: ⇒ "Elapsed time: 2275.128327 msecs" 49999995000000

17:54 Raynes: It does crazy shit like literally changing your code in order to sandbox it.

17:54 It is in no way accurately timeable.

17:55 xeqi: I've heard good things about https://github.com/hugoduncan/criterium for benchmarking

17:56 Sgeo: I should probably do things like homework instead of hating Konrad Hinsen

17:56 Raynes: Probably.

17:57 aperiodic: i can reproduce this particular result locally (partial seems to be about 3.5 times slower)

17:57 Raynes: Sgeo: What kinda homework?

17:57 aperiodic: casion: partial is slower, not faster

17:58 Sgeo: Senior Project, describing why I'd be good at my role in the group

17:58 casion: aperiodic: I know. I'm saying it doesn't make sense to me to even think partial would be faster

17:58 Sgeo: Overdue essay basically :/

17:58 hyPiRion: Heh, I'm writing a poker bot in Clojure now.

17:58 Raynes: Sgeo: So highschool stuff?

17:58 Or college stuff?

17:58 Sgeo: Raynes, college

17:58 I'm not in "Computer Science" though. I'm in "Computer Programming/Information Systems"

17:58 :/

17:59 Last semester, assuming I don't fail Intro to Drawing

17:59 Raynes: I was curious because high school would have placed you near my age group. Though I guess college does too.

18:00 aperiodic: casion: i didn't think the difference would be significant

18:00 casion: everyone here seems to be young

18:00 Raynes: casion: Define 'young'.

18:00 casion: aperiodic: well, iirc partial uses apply.. and #() is a macro

18:00 Raynes: < average age of ##c

18:00 Raynes: Lots of late 20s-late 30s, I think.

18:00 I'm an exception.

18:01 hyPiRion: Huh, I thought there were a lot of early 20s too.

18:01 casion: I just turned 30, but I'd figure I'm 'older' than most people my age

18:01 seems like there's a lot of similar people here

18:01 Raynes: You're only 12 years older than me.

18:01 That's only over a decade.

18:01 amalloy: aperiodic: the partial/lambda distinction is much more pronounced with + than with most functions

18:01 because (+ a b) can be inlined, but ((identity +) a b) can't

18:02 casion: finished college when I was 19, already had been doing embedded for 2 years at that point

18:02 amalloy: try using, eg, (let [f +] #(f % %2)) as your function, and they'll be pretty close

18:02 Raynes: I'm not doing the college thing.

18:02 casion: Raynes: good, IMO it's a complete waste

18:02 Raynes: I'm doing the work thing right now.

18:02 Sgeo: Is there a good reason that (partial +) doesn't work?

18:03 casion: then again, I have music degrees… which are essentially worthless :|

18:03 Raynes: lol

18:03 What are those for, exactly?

18:03 casion: one teaching, one performance

18:03 Raynes: What career choices do you have with music degrees?

18:03 casion: begging on street corners.

18:03 Sgeo: Or even (partial)

18:03 Raynes: Hahaha

18:04 mattmoss: I win? 40

18:04 casion: seriously, no one gives a flying fuck if you have a degree in any music related career except for teaching

18:04 and teaching music at anything but graduate level is drepressing

18:04 and I never made it that far anyway

18:05 S11001001: casion: partial is faster if you have like millions of them and not so much memory for all the classes that lambdas would require (i.e. partial has constant lambda-class cost :)

18:05 Sgeo: Is the speed really relevant?

18:06 It's the concepts that it expresses that are important, I think

18:06 aperiodic: Sgeo: probably not :)

18:06 S11001001: I don't care, but someone asked

18:06 aperiodic: but hey, it's interesting

18:06 hyPiRion: Sgeo: Oh God, no. If it were, then you're using the wrong language.

18:06 casion: S11001001: wouldn't partial be slower for anything > 3 args though?

18:06 S11001001: I like partial because it's pretty, and don't care about whatever cost from losing specialization of what have you

18:07 premature optimization &c

18:07 I'm a lisper, I don't care about consing

18:07 hyPiRion: casion: I envy musicians who program a lot. Most of them seem to excel at programming.

18:08 S11001001: anyway a sufficiently sophisticated compiler can optimize out a (concat ...) in the last arg position of apply :)

18:08 Sgeo: I hate partial because it requires two arguments, and that's a stupid thing to need to check for in a macro that emits a partial

18:08 casion: hyPiRion: at imperitive programming maybe :)

18:08 Sgeo: *at least two arguments

18:08 Bronsa: Sgeo: that's no longer true :)

18:08 Clojure 1.5.0-master-SNAPSHOT

18:08 user=> (partial +)

18:08 #<core$_PLUS_ clojure.core$_PLUS_@31818dbc>

18:08 Sgeo: Bronsa, awesome!

18:08 What about (partial)? I can think of a meaning for that

18:09 hyPiRion: casion: http://clojure-log.n01se.net/date/2008-03-26.html#22:29

18:09 Bronsa: Sgeo: what should that return?

18:09 a 0 arity function that does what?

18:09 Sgeo: (partial) would be a function that takes a function and other arguments and applys function to the arguments

18:09 ((partial) + 1 2)

18:10 hyPiRion: well, that's clutter though.

18:10 casion: hyPiRion: I wonder how far he's got… that will have a lot of difficulties with that model unless he's oversampling somewhere

18:10 hyPiRion: ((partial) + 1 2) would be just (+ 1 2)

18:11 Apage43: I think that was the idea, that you could move that first ) anywhere and get the same answer.

18:12 aperiodic: ok, the anonymous function literal is faster because it knows more about its arguments than whatever comes out of partial

18:12 that makes sense to me

18:12 Sgeo: the empty partial is identity, then?

18:13 Sgeo: aperiodic, I think that would only work if .. it were curried?

18:14 ,(identity + 1 2)

18:14 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (3) passed to: core$identity>

18:14 Sgeo: ,((partial identity +) 1 2)

18:14 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (3) passed to: core$identity>

18:14 Sgeo: Um, wtf am I thinking

18:14 Apage43: not identity, (fn [& args] (eval args))

18:15 casion: hyPiRion: you wouldn't happen to know if he spoke of this more?

18:15 hyPiRion: ,((fn [& [a & r]] (apply a r)) + 1 2)

18:15 clojurebot: 3

18:16 aperiodic: Sgeo: ah, right, there's an invocation in there i wasn't accounting for

18:16 hyPiRion: casion: I'm afraid not. But I know that he has an interest in audio.

18:17 casion: I really want to know how/if he handled the decay rate of the ion channels in the basilar membrane

18:18 octagon: hi, all. is there an existing function equivalent to (fn [x y] (fn [& args] (apply x args) (apply y args)))?

18:19 amalloy: &(doc juxt)

18:19 lazybot: ⇒ "([f] [f g] [f g h] [f g h & fs]); Takes a set of functions and returns a fn that is the juxtaposition of those fns. The returned fn takes a variable number of args, and returns a vector containing the result of applying each fn to the args (left-to-right). ((juxt a b c) x) => [(a x) (b x) (c x)]"

18:19 hyPiRion: octagon: would you be interested in the value x returns as well?

18:20 octagon: no, just the value of (apply y args) is needed

18:20 Apage43: ,((juxt list +) 1 2 3)

18:20 clojurebot: [(1 2 3) 6]

18:20 octagon: i am "funrolling" a sequence of functions all of the same arity

18:20 casion: hyPiRion: you have me google stalking him now :D

18:20 Sgeo: funrolling?

18:20 octagon: (reduce squash fns)

18:20 hyPiRion: casion: haha

18:20 octagon: where squash is my function above

18:24 gfredericks: a lot of the built-in HOFs won't work since you're using side-effects

18:24 or like juxt they will do a bit of extra work

18:25 xeqi: &((comp second (juxt list +)) 1 2 3)

18:25 lazybot: ⇒ 6

18:30 hyPiRion: &((comp second (juxt println +)) 1 2 3)

18:30 lazybot: ⇒ 1 2 3 6

18:33 Sgeo: juxt reminds me of something I saw in Haskell that's... related to arrows somehow

18:33 I don't entirely understand Haskell arrows though

18:33 amalloy: Sgeo: &&&, iirc

18:33 or ***? i forget

18:34 casion: thanks to sgeo, I've learned more about haskell in here than in #haskell ;)

18:34 Sgeo: o.O

18:35 casion: half-joking :)

18:35 mpan: what's the name-registration bot, again?

18:35 amalloy: yeah, juxt is &&&

18:35 Sgeo: mpan, NickServ

18:35 mpan: thanks

18:36 Sgeo: You're welcome

18:36 xeqi: I always think of ***, which appears at https://github.com/flatland/useful/blob/develop/src/useful/fn.clj#L94

18:36 ah, misread above

18:38 Sgeo: I can't imagine when to-fn would be useful

18:38 Erm, as-fn

18:39 S11001001: Sgeo: duck-typing

18:41 amalloy: S11001001: i'd describe it more as "weak typing". ninjudd is a much bigger fan than i am of APIs like "pass a function, but if it's not a function we'll make it one for you"

18:42 mpan: how does the "make it one for you" work?

18:42 amalloy: &(let [x 5, f (constantly x)] (f 'sdafjksde))

18:42 lazybot: ⇒ 5

18:43 mpan: oh, like assume if they give you val they want fn-that-gives-val?

18:43 TimMc: anti-trampoline

18:43 :-P

18:45 hyPiRion: I have had use for something similar - except that x is lazily evaluated.

18:47 jasonjckn: hi

18:51 mpan: hi

18:54 gfredericks: amalloy: you don't like those APIs because of ambiguous cases like vector/set/map/keyword?

18:54 hiredman: I may have found the perfect use for the stm

18:54 amalloy: that's one problem

18:55 Raynes: amalloy: I'm on your side regarding APIs like that.

18:55 hiredman: I model each pin on my beaglebone as a ref, then I can transactionally set them high or low (with a watcher that does the actual io)

18:56 amalloy: but i just don't like the looseness. it makes it hard to tell what's going on when you read a call to such an API. you can see (f x y), know the behavior of f, and have no idea what x and y are without further poking around in the local scope

18:56 gfredericks: amalloy: Raynes: I am on both of your sides regarding APIs like that

18:56 Raynes: I know you are, baby.

18:56 Sgeo: If you want to give a function a function that will always return a value, just do it in the call yourself

18:56 gfredericks: amalloy: it feels a lot like rails :)

18:57 amalloy: nice, hiredman. although, why not a single ref holding all of them? that would work, but i guess require a smarter watcher?

18:58 hiredman: amalloy: finer grained transactions of course... because I am flipping those pins high and low like crazy

18:58 * gfredericks googles beaglebone

18:59 hiredman: it's a little arm board like a rasberrypi

18:59 mpan: are you using... a serial port?

19:00 hiredman: gpio pins on the board, I am using them to control dc motors

19:01 axle_512: Style question… I am thinking of using clojure protocols for a data access layer (to MySQL.) My thinking is that if I switch databases, I can swap out the implementations. Is this a good practice/style in clojure?

19:01 arohner: axle_512: completely unrelated to the protocols question, IMO, you can't treat DBs as interchangeable

19:02 but yes, protocols would work there

19:03 axle_512: arohner: thanks!

19:04 mpan: could you treat a subset of their functionality as interchangeable, though?

19:05 one that would be enough to be useful

19:05 arohner: mpan: not really. select count(*) from table; is O(1) in mysql and O(n) or O(logn) in postgres. Also their syntax for a lot of things are different

19:06 Sgeo: What is clojure-slim?

19:06 arohner: so then you either have to treat the queries as strings, which aren't interchangable, or write an ORM that abstracts across them (thousands of LoC, and a giant effort to do properly)

19:06 Sgeo: I noticed it in the download

19:07 * Sgeo is about to set up an IRC bot with an unsandboxed Clojure

19:07 Sgeo: On a public channel

19:08 aperiodic: hiredman: are you running clojure on the beagleboard?

19:08 xeqi: Sgeo: don't do it

19:08 Sgeo: xeqi, the bot itself runs a sandboxed Linux environment

19:08 I think that environment is versioned? I'm not sure, I didn't make it

19:09 mpan: eventually someone will try to consume an entire infinite sequence by accident

19:09 xeqi: "by accident"

19:09 mpan: hey, I did it by accident locally

19:09 Raynes: Sgeo: selinux?

19:09 Sgeo: I think it's UMLbox

19:09 Raynes: I'm working on a selinux-sandbox-for-language-eval-as-a-service project with a friend.

19:10 Sgeo: And the first result for UMLbox is in fact by the person who made the bot, and UMLbox apparently

19:10 mpan: is it like process-per-request?

19:11 Sgeo: Requests all take place in the same environment, I think, but if someone screws it up, the bot operator can revert it

19:11 mpan: needing human intervention sounds tricky

19:11 Sgeo: There's maybe two channels where it's running

19:12 Incidentally, is there a .gz version of the Clojure distribution/

19:13 xeqi: is there a way to limit the number of Threads the jvm can start?

19:14 mpan: well you could have the operating system enforce it

19:14 but that doesn't sound like a nice answer

19:14 trying to see if the security api lets you

19:17 I thought it was possible with the security manager but I can't find it

19:19 xeqi: I haven't seen anything either :/

19:20 mpan: you could conditionally forbid everything in the java api that would create a thread

19:20 that sounds hard though

19:20 but I recall hearing someone had done it before for clojure

19:21 xeqi: heh, I tried to convince someone of blocking some of it

19:25 axle_512: arohner: more what I was thinking was something like a protocol for dealing with users. Create user, list users, get details for individual user, and delete user. Then the SQL specific details for each database would live behind those functions.

19:25 arohner: ah, data access layer. Much more manageable.

19:25 augustl: is there a way to make a jar that somehow makes its "resources" available directly in the file system as opposed to packaged inside a jar? Need to shell out to python, so the files python calls needs to be in the "normal" fs.

19:25 axle_512: arohner: And still a good use for protocols? Or is there a better way?

19:26 hiredman: aperiodic: yes

19:26 aperiodic: with the oracle arm jvm

19:26 arohner: axle_512: protocols dispatch on the class of the first argument, and are built for speed

19:26 xeqi: axle_512: namespaces?

19:27 hiredman: I've got a little rover I am building on what is left of a $20 rc car

19:27 arohner: axle_512: normal fns might get you a long way

19:28 mindbender1: "I don't want to die in a language I can't understand" -- Richard P. Gabriel

19:29 axle_512: arohner: thanks, makes sense.

19:30 xeqi: thanks, let me think on that too.

19:34 xeqi: I think what you mean is to just use a different namespace per impl… all with the same function signatures. Then I can swap them out interchangably. (Without need for protocols?)

19:36 xeqi: axle_512: yep, and if you alias (require '[blah.postgres :as db]) and use them db/save-user then all you have to change is the use line

19:36 assuming your not changing them at runtime

19:36 then namespaces wouldn't be easy, if workable

19:39 axle_512: xeqi: appreciate it!

19:55 abcnever: Hi I'm new to clojure and I'm kind of confused by square brackets in clojure. I have googled it but I'm still not sure what exactly is square brackets used for. Is it vector?

19:56 hiredman: ,(vector? [])

19:56 clojurebot: true

19:56 abcnever: oh that's neat 0.0

19:57 Thanks!

20:17 augustl: I need to invoke a python script that uses code in the resources/ of my jar. But that only works when working with the checked out code.. When I package the jar, the resources/ aren't directly in the file system, so the python script doesn't find them

20:17 any suggestions?

20:20 mpan: extract to a temporary dir on path at runtime? that sounds messy but it would do it

20:20 amalloy: don't distribute a jar, get a smarter python program...

20:20 Apage43: http://docs.python.org/library/zipimport.html

20:21 rather, the functionality is build in, so you should just be able to add "file.jar/resources" onto your python import path

20:22 it may actually be looking for the ".zip" extension though, which could be problematic

20:34 augustl: mpan: hmm toat could work

20:34 amalloy: for some reason, building Google Closure requires both python and java

20:35 Apage43: I'll investigate

20:35 jrajav: "For some reason"? They're fracking Google :P

20:35 augustl: s/toat/that

20:35 jrajav: It's not code until Python or Java is in there somewhere

20:35 augustl: would be nice if they could pick just one..

20:36 ivan: Google Closure is 4 or 5 different tools

20:36 augustl: would still be nice if the dependency script from the library was java, though

21:04 clj_newb_2345: what is the correct way to change a javascript object to a clojurescript object?

21:07 akhudek: clj_newb_2345: js->clj

21:07 I think.

21:07 clj_newb_2345: ah; for some reason, I wa susing js->cljs

21:07 *using*

21:07 Sgeo: How common is do-template/

21:07 *Commonly used

21:13 amalloy: Sgeo: ~never

21:13 Sgeo: o.O but it looks useful for various things

21:14 tomoj: why does clojurescript have ASeq?

21:15 seq is identity on ASeqs, but this seems to mean that every ASeq should be an ISeq

21:15 which appears to be the case in core

21:17 jvm translation artifact?

21:30 Sgeo: Is jayfield someone who comes here?

21:31 http://blog.jayfields.com/2011/01/clojure-using-java-inner-classes.html 403's for me

21:32 amalloy: tomoj: i don't think think so. it looks like dnolen added it in 653a26e3, though i can't immediately see why

21:35 tomoj: strange

21:35 "wip", but it still doesn't appear to be used

21:35 except for seq

21:36 unlink: How do I map over the values of a hash map in Clojure? Looking for something equivalent to (fn [f xs] (into {} (for [[k v] xs] [k (f v)])))

21:38 howard_guo: , (let [a 1] a)

21:38 clojurebot: 1

21:39 howard_guo: , (def foo (Thread/sleep 100))

21:39 Sgeo: , (let [+ -] (+ 1 1))

21:39 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

21:39 0

21:39 Sgeo: Hmm, there's a funny example of Haskell code but I don't think I can re-create it in Clojure

21:40 howard_guo: C:

21:40 Sgeo: Well, I can, but it wouldn't be as amusing

21:40 let 2 + 2 = 5 in 2 + 2 results in 5 in Haskell

21:40 tomoj: huh, why didn't that get inlined?

21:40 ludston: Could do (loop [keys data map] (if (empty? keys) map (recur (rest keys) (rest data) (assoc map (first keys) (first data)))))

21:40 unlink: Something like the Functor instance on Map in Haskell :-)

21:40 ludston: Not very efficient though

21:41 tomoj: unlink: well in 1.5 maps are Foldable

21:41 but http://dev.clojure.org/jira/browse/CLJ-1049

21:41 and you can't use the result it like a map without reducing it into a new map anyway

21:42 Sgeo: Functor needs to be separate from other concepts

21:42 Seriously

21:42 This is absurd

21:42 howard_guo: ,(import 'sun.misc.Unsafe)

21:42 clojurebot: sun.misc.Unsafe

21:42 howard_guo: eh?!

21:44 Sgeo: I doubt you'll be able to use it

21:44 amalloy: Sgeo: i've noticed all the clojure libraries are absurd. save your breath and write better ones

21:44 Sgeo: ,sun.misc.Unsafe

21:44 clojurebot: sun.misc.Unsafe

21:45 howard_guo: ,(do (import 'sun.misc.Unsafe) (sun.misc.Unsafe/getUnsafe))

21:45 clojurebot: #<CompilerException java.lang.RuntimeException: java.lang.NoSuchFieldException: getUnsafe, compiling:(NO_SOURCE_PATH:0)>

21:45 howard_guo: :(

21:47 ,(prn 1)

21:47 clojurebot: 1

21:47 howard_guo: ,(prn (System/getProperty("java.version")))

21:47 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn>

21:47 howard_guo: ....

21:47 ,(prn (System/getProperty "java.version"))

21:47 clojurebot: #<SecurityException java.lang.SecurityException: denied>

21:47 howard_guo: hahaha...

21:49 ,(import 'java.beans.Expression)

21:49 clojurebot: java.beans.Expression

21:50 tomoj: maybe try hacking lazybot in PM?

21:50 howard_guo: no intention of hacking, just having some fun

21:54 ,(do (import 'java.beans.Expression) (.getValue (Expression. System "getProperty" (into-array String ["java.version"]))))

21:54 clojurebot: #<RuntimeException java.lang.RuntimeException: java.lang.InternalError: bouncer cannot be found>

21:55 gfredericks: howard_guo: but your fun is noisy

21:55 you can use a private message to cavort with the bots

21:55 howard_guo: ok

21:55 sorry

21:55 gfredericks: no worries; I've done it too often myself

21:55 howard_guo: what is a java bouncer?

21:58 tomoj: btw if you manage to find a hole, that's good and should be reported to clojail

21:58 howard_guo: yeah... im not a bad guy

21:58 tomoj: ie hacking encouraged, it makes the jail better

21:59 ludston: Don't worry howard_guo, *I* think you're a bad guy.

21:59 howard_guo: ^^

22:01 xeqi: I think lazybots pretty secure now, though there are ways to crash it

22:01 howard_guo: this morning I was debugging my network application, it uses linked blocking queue to process incomming requests

22:01 tomoj: I wonder if binding is only outlawed because push-thread-bindings is dangerous?

22:01 howard_guo: and I then noticed , for some reason, the requests get lost after few thousands of them

22:01 so I spent few hours to debug that, no progress

22:01 and then I came here...

22:02 amalloy: tomoj: yes

22:05 howard_guo: my Clojure networked application needs a queue to sequentially process incoming requests, is it better to use linked blocking queue or build a queue using Clojure's concurrent mechanism?

22:05 I don't need many functions, just an add and a remove

22:07 xeqi: (doc pop)

22:07 clojurebot: "([coll]); For a list or queue, returns a new list/queue without the first item, for a vector, returns a new vector without the last item. If the collection is empty, throws an exception. Note - not the same as next/butlast."

22:07 howard_guo: um...

22:08 I thought about building the queue using clojure's functions

22:08 but then realized, if 1000+ requests are queued, each time an entry is popped from the queue, the queue needs to be copied, popped and then assigned back to the atom?

22:09 ludston: Have you considered using JMS?

22:10 howard_guo: no I have not

22:10 I will check it out

22:11 but linked blocking queue shouldn't break after just a few thousands of queued things right?

22:11 ludston: I'm not sure about any clojure interfaces for it. It's "Java Messaging System" and it's pretty much just consists of a queue sevlet thingy that you can push and pull messages from.

22:11 amalloy: clojure's immutable data structures are much more efficient than just copying the whole thing

22:11 howard_guo: thank you

22:12 amalloy: conj and pop are both O(1) on a queue

22:12 howard_guo: cool

22:12 my clojure network app, reads messages from sockets, put them into a linked blocking queue

22:12 then another thread, takes entries from the queue and process them

22:12 tomoj: conj is O(log_32 n), pop is O(1)?

22:13 howard_guo: I started a client, and in a (doseq [I (range 10000)] loop, it sends those messages through socket

22:13 and I noticed that server app's linked blocking queue no longer returns when "take" is called. after around 3000 messages are queued

22:13 really weird

22:14 tomoj: I guess pop is O(log_32 n) as well

22:14 amalloy: tomoj: did you watch spiewak's talk at the second conj, about the implementation of functional queues?

22:14 tomoj: no

22:14 is it amortize O(1)?

22:14 akhudek: tomoj: log_32 n is really small

22:14 amalloy: yes

22:15 pop is, anyway

22:15 tomoj: cool

22:15 amalloy: conj is log32

22:15 howard_guo: conj to vector is log32?

22:15 is conj to list O(1)?

22:16 amalloy: but i still prefer to call that O(1) anyway

22:17 tomoj: I'm still confused about that

22:17 akhudek: ,(/ (Math/log 1000000) (Math/log 32))

22:17 clojurebot: 3.986313713864835

22:18 amalloy: tomoj: you know the formal definition of big-O?

22:18 tomoj: ,(/ (Math/log 1000000) (Math/log 2) 5)

22:18 clojurebot: 3.986313713864835

22:18 tomoj: yeah

22:19 Sgeo: I'd imagine conj to a list os O(1)

22:19 howard_guo: hope so...

22:20 tomoj: seems like any argument for using "O(1)" for O(log_32 n) would not be hard to apply to O(log_2 n)

22:20 Sgeo: A list is just a value and another list, prepending to it shouldn't matter how much other stuff is in the list

22:20 howard_guo: :)

22:20 amalloy: tomoj: sure, that's a fair objection

22:20 Sgeo: Why not just say that conj to vector is O(log n) but that it's fairly small

22:20 tomoj: except the magnitudes of "too big to care" is different?

22:21 amalloy: but if you put log32 in between 1 and log2, it's a lot closer to 1 than to log2

22:22 some of it is also just convenience. it's easier to characterize the running time of some larger algorithm if you pretend insertions to vectors are constant time, instead of pedantically carrying along the log32 through the whole analysis

22:24 tomoj: ok

22:25 but what confuses me is that it is acceptable to drop it

22:25 or s/that/whether/

22:25 Sgeo: Mathematically, no.

22:25 But what amalloy is trying to get at is that in practical usage, the amount of time is going to be small even with large vectors

22:26 It doesn't mean that it becomes O(1), because it doesn't

22:26 But it does mean that when trying to choose an algorithm, O(log_32 n) might be as negligable as O(1) is, I think

22:26 howard_guo: you'll probably need Google scale challenges to notice that difference :D

22:27 tomoj: and the reason we don't say binary search is "practically O(1)" is because trees big enough were the difference is noticeable are common?

22:27 s/were/where/

22:27 amalloy: tomoj: i think so

22:27 Sgeo: I would say that it's wrong to say that it's O(1), just say that it's as negligable as O(1)

22:28 It's O(log n) with a very small I'm not sure the word

22:29 tomoj: so if some years from now, datasets 5x bigger than what we have now are common, will we have to increase the arity of our tries?

22:29 wait, that 5x seems wrong

22:30 is it actually 32^5 :O

22:30 metellus: one thing to keep in mind in all of this is that O(1) does not guarantee fast and O(log n) doesn't necessarily mean slow

22:30 in practical cases, coefficients do matter

22:31 and when the JVM is concerned, log_32 (n) never goes above something like 7

22:31 amalloy: tomoj: something like that. i'd say more like 2^32

22:31 because that's when we'll finally need to use a long rather than an int for an array index

22:34 tomoj: so at n=4.789e52 log_32 never gives above 35, which is where log_2 is now

22:34 which is more than the number of stars in the observable universe

22:35 based on that I'm going to pretend to myself that I'm not confused anymore :)

22:44 howard_guo: If you have some spare time to spend, please take a look at this issue in my Clojure network application:

22:45 https://github.com/HouzuoGuo/Aurinko/issues/12

22:45 I have tried very hard but still cannot figure out why LinkedBlockingQueue fails me

22:45 Hodapp: did my eyes just observe... Counterclockwise hot-swapping my code in as I evaluate it?

22:45 howard_guo: wow really it does that?

22:46 Hodapp: well, now that I think of it, I suppose with Quil it makes more sense because I was redefining the 'draw' function, which it calls every frame

22:46 amalloy: tomoj: number of stars in the observable universe seems *way* smaller than that, isn't it?

22:47 Hodapp: but even so, I am surprised that the updated 'draw' is what's used in all other places then

22:47 howard_guo: wow that is really handy

22:47 Hodapp: I certainly could not do this with Processing

22:47 akhudek: amalloy: "The observable universe contains between 10^22 and 10^24 stars…"

22:48 amalloy: right. 10^52 sounds more like the number of electrons in the observable universe, not stars

22:48 tomoj: wiki says number of atoms is very roughly 10^80

22:49 akhudek: I can see the blog post now "Clojure for universe-scale processing"

22:49 howard_guo: hahahaha

22:49 "Clojure has solved the universe"

22:50 Sgeo: If I have some program that's written in Java, and, say, it's a chat program, I should be able to, with a Java decompiler and Clojure, make bots to connect to it?

22:50 (Java decompiler just to know what classes and functions to use, I'm aware Clojure doesn't need source code)

22:51 howard_guo: decompiled clojure code is quite... ugly

22:57 ivan: howard_guo: do you... reload your code after ~1000 offers?

22:57 howard_guo: reload my code?

22:57 sorry I don't get it

22:57 ivan: not knowing anything, the only thing I suspected was offering to a new/wrong LinkedBlockingQueue

22:57 howard_guo: oh..

22:58 thanks for that, I'll check it anyway

23:01 Hodapp: aaaaand I crashed Eclipse

23:01 Sgeo: I've had a long-standing complaint about Clojars

23:01 I should just try to put a web app on Heroku or something to solve it

23:02 Although.... hmm, the possibility of malicious jars... I don't know how to fix that

23:02 Hodapp: all I want to do is (1) stop the Clojure application I just started and (2) restart it without everything exploding

23:02 howard_guo: and boom

23:02 Sgeo: (I just want a tool to browse the source of uploaded jars)

23:09 Although, do lein jars and uberjars precompile all the .clj? If so, then my idea is sort of useless

23:13 Hodapp: jeebus, even without getting the hang of Clojure yet completely, I am finding it rather awesome that I can swap in new function definitions while the damn code is running

23:14 ivan: Sgeo: I just track down everyone's git repos and use my hacky build system to build everything

23:14 all 242 of them

23:14 Sgeo: I meant more in terms of reading the source to get an understanding of what it does

23:14 xeqi: Sgeo: out of curiousity.. whats your complaint?

23:14 ivan: Clojure libraries are almost always .clj source in the jar

23:15 Sgeo: xeqi, that it's not convenient to browse the source of a library on Clojars right on the site

23:15 Raynes: Sgeo: Clojure code is very rarely aot'd at all.

23:16 uvtc: Sgeo, I think the tool to browse a jar's source code is github. :) That is to say, the canonical clojars page for a given library should almost always contain a link to the lib's github page, and you can browse the code there.

23:16 ivan: but what if the jar code does not match the VCS code!

23:16 Raynes: You can just download the jar and open it up in emacs.

23:17 uvtc: Just FYI, all jars are directly available at http://clojars.org/repo/ .

23:20 ivan: someone ought to write a tool to verify that everyone's releases correspond to a git commit

23:21 and then read every line of code

23:21 uvtc: xeqi: Clojars feature request: On a given library's Clojars page, also provide a direct link to the jar somewhere on the page.

23:21 ivan: couple days ago I found a unit test downloading an unsigned clojure.jar over HTTP

23:21 Sgeo: ivan, o.O wtf

23:22 Is there a process for getting malicious stuff removed from clojars?

23:22 Raynes: uvtc: I'm against that.

23:22 uvtc: It'll encourage new people to try to download and 'install' the jar.

23:22 The way it is now, they're forced to read about Leiningen. Pretty much, anyways.

23:23 ivan: I wanted that feature at some point, then just used rsync to get all of clojars

23:23 Raynes: Sgeo: Well, the first step is for people to not download malicious stuff.

23:23 tomoj: to get all the docs and source metadata, wouldn't you need to actually load the code? so LXC per artifact?

23:24 Raynes: Sgeo: clojars will require jar signing and such for the main maven repo soon.

23:24 So that might help.

23:24 uvtc: Raynes: Ah. Ok. Well, anyway, easy enough to grab the jar from /repo/group-id/artifact-id too.

23:24 Raynes: I imagine that if you found something malicious, you could get it removed by asking technomancy.

23:25 xeqi: Sgeo: https://github.com/ato/clojars-web/wiki/Contact

23:26 uvtc: One person's malicious is another person's delicious.

23:26 Wait, I didn't say that.

23:27 See, as soon as I see Raynes here I start using all by late-night humor.

23:28 Speaking of Raynes, if anyone's interested, I've been experimenting with htmlizing and colorizing the IRC logs that he collects. I've started putting them at http://www.unexpected-vortices.com/clojure/irc-logs/index.html .

23:28 (just the ones for #clojure)

23:29 aperiodic: oh rad, you did the monospacing for the evaluation requests!

23:29 (inc uvtc) <3

23:29 ugh

23:29 (inc uvtc)

23:29 uvtc: Uh oh.

23:29 lazybot: ⇒ 1

23:29 ivan: "SANBOX DENIED"?

23:30 aperiodic: hmm

23:30 (inc aperiodic) ; garbage

23:30 lazybot: You can't adjust your own karma.

23:30 uvtc: (inc aperiodic) ; hi!

23:30 lazybot: ⇒ 1

23:31 aperiodic: oh, all bot messages are monospaced

23:31 good enough

23:31 uvtc: aperiodic: Yes. I think that was requested yesterday.

23:31 aperiodic: well, it would be cool if the input was too

23:31 is this in a real repo yet?

23:31 uvtc: I tried having all the comments be the same default color, but I just liked reading them in color better.

23:31 So, alas, can't make everyone happy.

23:32 aperiodic: Ah, right. I need to create a github repo for the project.

23:32 aperiodic: you could just use lazybot & clojure as dependencies, and hook into however they find the forms to evaluate

23:33 uvtc: I don't yet know why http://www.unexpected-vortices.com/clojure/irc-logs/2012/09-15.html#06:35:17 isn't rendering the last character correctly (in my browser).

23:33 aperiodic: I think maybe that's a little fancier than what I've done so far.

23:37 Hodapp: hrmmm, mixing Clojure with a very-stateful-API is kind of weird

23:38 aperiodic: uvtc: are you putting it in a repo now? ;)

23:39 uvtc: Yes, just need to fill in the README.md ... just a few moments.

23:39 aperiodic: excellent!

23:46 uvtc: aperiodic: https://github.com/uvtc/colorize-irc-logs

23:47 aperiodic: (inc uvtc)

23:47 lazybot: ⇒ 2

23:48 uvtc: Oooh! I'm moving up in the world. :D

23:48 aperiodic: yup; at the conj, we'll all line up by lazybot karma before every meal

23:57 Sgeo: (karma sgeo)

23:58 aperiodic: $karma Sgea

23:58 lazybot: Sgea has karma 0.

23:58 aperiodic: $karma Sgeo

23:58 lazybot: Sgeo has karma 0.

23:58 aperiodic: i can type

Logging service provided by n01se.net