#clojure log - Feb 05 2010

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

0:33 hiredman: user=> (expression-info '(jop / (float 4) (float 1.1)))

0:33 {:class float, :primitive? true}

0:33 :D

0:35 chouser: huh!

0:35 does it work for any java operator?

0:40 hiredman: chouser: no

0:40 still a work in progress, the operands need to be of the same type

0:41 I don't imagine that will change, the dispatch would be taken care over via a protocol like c.l.Numbers

0:41 of

0:42 which at the bottom level would call jop something

0:45 at least those are my thoughts, who knows what rhickey is up to :P

0:45 chouser: :-)

0:51 hiredman: gah, suddenly none of the three web browsers I have installed are working and I am without reference to javadocs

0:51 chouser: javadoc from repl-utils might still work via swing

0:54 * qed is scared of the new clojure.contrib changes

0:54 qed: someone comfort me

0:55 hiredman: contrib has been altered, pray that stuart does not alter it further

0:55 qed: heh -- im actually fond of his changes, just not so fond of changing all of my code

1:22 /go clojurebot

2:10 LauJensen: Morning team

2:22 * ndimiduk waves at LauJensen

2:26 tomoj: is there any alias for the current ns inside the ns declaration?

2:27 as in, to avoid the duplication in (ns foo.bar.baz.bang (:require [foo.bar.baz.bang [biz bing bong]]))

2:27 guess it's not that bad

2:28 really for me it becomes (ns foo.bar.baz.bang (:require [foo.bar.baz.bang [[biz :as biz] [bing :as bing] [bong :as bong]]]))

2:28 which is ugly but not too much work to type, I guess

2:33 vu3rdd: Is there a way to get source code thru lein? (like apt-get source)

2:34 hmm.. ignore my question. I misunderstood lein.

2:59 LauJensen: lein just gets jars, but if those jars contain the source, you can get it at from Emacs, M-x ; I think

2:59 s/it at/at it

3:08 hiredman: http://gist.github.com/295631

3:08 way too excited about this I think

3:13 tomoj: hiredman: what exactly is it you're excited about?

3:13 I don't understand the gist :(

3:13 * kotrin seconds tomoj

3:14 hiredman: if you look at the last method in the output of javap, that is what is the body of the fn function

3:14 tomoj: ok

3:15 hiredman: and the jop compiles directly to a call to fadd instead of clojure.lang.Numbers/add

3:15 tomoj: I think whatever you're doing is simply beyond me :)

3:15 oh, hmm

3:15 hiredman: fadd takes two floats off the stack and pushs the result of adding them onto the stack

3:15 tomoj: so, are you compiling certain pieces of clojure directly to fast jvm bytecode?

3:16 hiredman: I don't know, it is possible, but speed is not my object

3:16 tomoj: what _is_ your object?

3:16 hiredman: that is part of what is exciting, I have a beachhead in the compiler

3:18 if the operations in Numbers are replaced with a protocol, they will need math ops that don't compile to method calls

3:21 LauJensen: Wow

3:22 hiredman: The term beachead is new to me, can you explain that without tipping over your bikeshed-o-meter? :)

3:23 hiredman: http://en.wikipedia.org/wiki/Beachhead

3:24 LauJensen: Ok

3:24 unfo-: hiredman is going to peacefully invade the compiler and cause upheave its internal structures?-)

3:26 hiredman: unfo-: in an alternate universe (my personal clojure repo)

3:26 unfo-: :-)

3:38 nathanmarz: i'm having a weird issue where "lein compile" works but spits out a ton of "ZipException"'s - does anyone else see this?

3:39 hiredman: weird

3:40 maybe some of the jars you depend on are damaged?

4:11 nathanmarz: my program still runs though... i guess i'll try unjarring and rejarring manually

4:33 avarus: hi

4:36 AWizzArd: hey avarus

4:37 esj: morning all

4:38 avarus: how are you guys?

4:38 AWizzArd: tired

4:39 esj: ditto that

4:39 Friday is always brutal

4:39 avarus: hehe

4:46 brb :)

5:23 AWizzArd: Bald ist Wochenende :)

5:25 krumholt_: yes!

7:14 vu3rdd: LauJensen: good afternoon

7:14 LauJensen: Hey :)

7:15 vu3rdd: going thru the cloneit code

7:16 what does the line 19 do? http://github.com/LauJensen/cloneit/blob/master/src/cloneit.clj

7:16 I am still confused with java.. printTo is a method of who?

7:19 LauJensen: http://joda-time.sourceforge.net/api-release/org/joda/time/format/PeriodFormatter.html

7:23 vu3rdd: Ok, so toPrinter gives a PeriodPrinter and then we use the printTo to print it?

7:25 I should re-read chapter 3 of programming clojure.

7:26 AWizzArd: Moin Lau

7:36 zaphyr: is there something like a destructuring let*?

7:43 LauJensen: vu3rdd: I think thats right

7:45 Moin AWizzArd

7:46 Raynes: LauJensen: Did you see that C# version of the newsgroup scraper in the comments on your Clojure vs Scala & Ruby thread?

7:47 Guy said it completed in like, 10 seconds. Shocked me.

7:49 LauJensen: Raynes: Yea I dialoged with the author - I haven't benchmarked it yet, but his system is quite a bit faster than mine. I've promised him that once I get some time to set up Mono I'll take it out for a spin

7:52 vu3rdd: LauJensen: Thanks

7:52 LauJensen: you should write a book on clojure

7:57 AWizzArd: Moin ulfster, alles klar?

7:57 ulfster: Moin

7:59 spariev: is that #clojure.de :) ?

8:00 AWizzArd: spariev: nah, just a german greeting. And the clojurebot also knows "alles klar" *g*

8:00 ulfster: funny thing is, i am german ;)

8:00 AWizzArd: That was the intention.

8:01 vegai: where's this thread?

8:02 esj: i like alles klar

8:02 spariev: I only know "aller klar" and "Ich moechte essen" in german :)

8:02 esj: although I'm not German

8:04 AWizzArd: Though the bestest language of them all is Clojure.

8:08 Raynes: I speak redneck, or at least LauJensen certainly thinks I do. :>

8:20 jcromartie: Clojure.org says "for a better experience, try running it via the JLine ConsoleRunner"

8:21 but I found JLine to be incredibly frustrating and incomplete compared to rlwrap, which is available for cygwin, macports, and any linux distro

8:21 It should get a mention. I feel like it's a hidden gem and most people don't know about it.

8:22 unfo-: LauJensen, clojure vs scala & ruby - where? -)

8:23 chouser: jcromartie: I use rlwrap too, but am under the impression most people use emacs slime and spend half their time trying to get that to work instead of learning Clojure. *shrug*

8:23 Raynes: unfo-: http://www.bestinclass.dk/index.php/2009/12/clojure-vs-ruby-scala-transient-newsgroups

8:23 unfo-: ty

8:23 since those are the three languages i am currently interested in

8:24 Raynes: It's not a real comparsion.

8:24 I mean, not in the way you might think it is.

8:25 unfo-: from a brief glance it's pretty much what i wanted :)

8:34 ohpauleez: haha chouser, are you still a vimclojure user

8:34 AWizzArd: ohpauleez: why not?

8:34 jcromartie: my main case against Ruby: "or" exists

8:34 http://gist.github.com/295413

8:34 cemerick: chouser: that can be easily parameterized to "I use % too, but am under the impression that most people use emacs %2 and spend half their time trying to get that to work instead of learning %3. *shrug*"

8:35 ohpauleez: no no no, I'm a vimclojure user

8:35 I love it

8:35 chouser: yeah, well, really just vim. I still don't do the live repl integration stuff.

8:35 wlr: (> help-request-per-vim-user help-request-per-emacs-user) -> true

8:35 chouser: cemerick: you're right. I don't know why I'm feeling snarky this morning.

8:35 ohpauleez: I rarely use the live repl, but I do like the doc lookup and omnicompletion

8:35 AWizzArd: I don't use vim, but if it works well for some people it's perfectly fine I think.

8:35 jcromartie: yeah I gave up on swank for my current project because I can't be bothered to sort out the current working directory issue

8:35 ohpauleez: totally AWizzArd, I completely agree

8:35 cemerick: chouser: s'ok. Emacs brings that out in people.

8:36 ohpauleez: it's the first lisp I felt like I COULD pick an editor

8:36 cemerick: Slime is a compounding factor.

8:36 jcromartie: I should be loading resources from the classpath or env vars or something

8:36 * cemerick ducks

8:36 ohpauleez: usually you're pushed into emacs

8:36 chouser: Actually, I think it's the emacs advocates that bring it out in me. Emacs itself bothers me rather less.

8:36 s/the emacs/some emacs/

8:36 * tcrayford is happy using both emacs and vim

8:36 Raynes: I tried to use Vim. Didn't work out for me.

8:37 * _fogus_ uses clojure-mode only. Complexities solved

8:37 chouser: I ought to spend a chunk of time improving my clojure environment. But investing in either single-threaded editor with ancient scripting language seems a poor use of time.

8:37 rhickey: emacs + clojure-mode + paredit seems much simpler than Slime

8:38 cemerick: vim's no walk in the park, IMO either, but the issue is dismissive evangelism rather than...just about anything else.

8:38 jcromartie: _fogus_: right on

8:38 bash + rlwrap + clojure for my repl

8:38 Raynes: I don't know how I would code without an integrated REPL.

8:38 * tcrayford uses slime and all the bells. Not even hard if you're using lein

8:38 tcrayford: also my refactoring tool depends on slime

8:39 rhickey: does slime do Java completion?

8:39 tcrayford: yep

8:39 _fogus_: I have to spend a few moments to get rlwrap working... jline seems to go into limbo too often

8:39 jcromartie: _fogus_: there's nothing to get working :)

8:39 install and rlwrap-away

8:40 so what's the deal with working directories and swank-clojure-project

8:40 _fogus_: Even better

8:40 tcrayford: jcronmartie, you might have to use ,cd inside slime to switch your working dir to be correct

8:40 vu3rdd: tcrayford: Is there anything to be done to get java completions in slime?

8:41 tcrayford: just c-c tab inside slime and it'll complete it

8:41 if you want autocomplete, go look at company-mode (its on elpa) and slime-company.el (on the emacs wiki)

8:41 jcromartie: tcrayford: would I start slime, cd, and *then* start swank-clojure-project then?

8:42 Raynes: When I do swank-clojure-project, it asks me which directory I want to be root.

8:42 After that, everything is perfect.

8:42 * tcrayford uses lein instead of swank-clojure-project

8:42 jcromartie: yay!

8:43 vu3rdd: tcrayford: thanks. will look into it. I can't get C-c TAB to work in my slime..

8:44 tcrayford: vu3rdd: m-x slime-complete-symbol

8:44 vu3rdd: bind that to something if you have something conflicting with C-c TAB

8:45 vu3rdd: tcrayford: it tries to find it, but says can't find completion for so and so.

8:45 tcrayford: what are you trying to complete?

8:46 vu3rdd: Say, (StringBuffer.)

8:47 tcrayford: insert (StringBuf and tab it

8:47 it works fine here

8:48 vu3rdd: tcrayford: still same issue.

8:48 I don't have the company mode installed though..

9:00 chouser: Bleh. http://www.kroah.com/log/linux/android-kernel-problems.html

9:02 jcromartie: Android is dead to me.

9:02 chouser: I guess it's still less closed and more Clojure-friendly than iPhone, but ... bleh.

9:02 jcromartie: only slightly

9:02 I still haven't seen clojure running well on Dalvik

9:03 a jailbroken iPhone runs Java better

9:03 chouser: huh

9:03 Chousuke: google is being really foolish with android :

9:03 it might work for them now but they're just wasting resources in the long run :(

9:04 zaphyr: giant globalised tech company wasting resources? unheard of! :)

9:04 jcromartie: android is just another marketing idea

9:04 trying to get the Google name in more places

9:05 techwise, eh... take it or leave it

9:05 chouser: zaphyr: :-)

9:05 jcromartie: unless I want to build a mobile OS I don't care about the code for a mobile OS

9:05 so open source it or not, it doesn't matter to me

9:05 it's not like you can really contribute

9:06 ltyphair: i got a free droid last night at ADL2010 in Austin. Planning on trying to get clojure running on it.

9:06 jcromartie: ltyphair: was ADL good?

9:07 ltyphair: the droid was nice. no power, my laptop ran out of juice by the time the code session started

9:08 so if you are going don't turn on your laptop till the end.

9:08 jcromartie: k

9:08 I might go in DC

9:08 ltyphair: jcromartie: i would go. just for the chance of a real device to dev on.

9:09 jcromartie: and they will probably have all the wrinkles out.

9:09 jcromartie: yeah

9:13 rys: You get the java runtime on Android?

9:14 jcromartie: rys: no, just a custom VM

9:14 you compile Java bytecode to Dalvik (the VM) bytecode before loading it on the device

9:14 so you can compile *compiled* Clojure code to Dalvik bytecode

9:15 but you can't compile on the device since Clojure produces Java bytecode and those libraries don't work on Dalvik

9:15 that's my understanding of it

9:16 * zaphyr wonders if you can generate dalvik bytecode dynamically

9:16 jcromartie: where's cinc when you need it :)

9:20 ltyphair: there is an android scripting environment but does not do clojure http://code.google.com/p/android-scripting/

9:20 spariev: I'm trying to translate from java the following code TermAttribute term = (TermAttribute) stream.addAttribute(TermAttribute.class)

9:21 if I write (.addAttribute stream (class TermAttribute)) compiler complains addAttribute() only accepts an interface that extends Attribute, but java.lang.Class does not fulfil this contract.

9:22 so, how can I do TermArtribute.class in clojure ?

9:22 jcromartie: (.class TermAttribute)

9:22 chouser: Just TermArtribute actually

9:23 jcromartie: ah

9:24 spariev: chouser: thanks, that works

9:28 ohpauleez: I think this weekend I'm going to wrap the jdb stuff up for clojure, so I can use a clojure repl as my jdb interface

9:30 AWizzArd: chouser: btw, about yesterday: lock, deref atom, put the derefd value into a w-l-v... one other idea about agents which can do the locking and derefing implicitly:

9:30 the challenge with them was that the caller thread can't know if there was an exception, because of a constraint.

9:31 But one possibility is that my transaction macro uses a promise as an argument which the agent will then deliver. This way a thread can block as long the agent is working on its query, and then also detect if there was an Exception or not.

9:34 chouser: ohpauleez: I didn't know you were working on anything like that. sounds *fantastic*

9:35 te: good morning

9:35 chouser: AWizzArd: yes, there would be a few ways to make agent errors report back the way you wanted, but I think it's just a poor fit.

9:35 ohpauleez: I have real need for it in my day-to-day work. I've been working on a few clojure projects in the off time, but none that public on github yet

9:36 vu3rdd: tcrayford: No luck with the java auto complete thing.. does it work without slime-company.el?

9:36 chouser: AWizzArd: the way exceptions were working strikes me as a symptom, not the root problem.

9:43 AWizzArd: chouser: where do you see a root problem?

9:44 chouser: using agents for sychronous tasks

9:45 AWizzArd: Well, there can easily be tens of DBs that are asynchronously transactioned.

9:46 (send db1 ...), (send db2 ...) vs (locking db1 ...), (locking db2 ...)

9:51 rhickey: asynchronous transaction seems like a contradiction

9:55 AWizzArd: Well, both solutions have +/- the same programmatic complexity, so I can easily go with either agent+promise or atom+lock to do the transaction.

9:55 chouser: the cells model is really very close, deriving from the use of locks.

9:56 AWizzArd: Yes, the cells sound very interesting.

9:56 Maybe I now do it with locks+atom and can later remodel it to the Cells.

9:56 chouser: for example, if you do want to support a transaction on multiple dbs, you'd just list them all in the same form so that it could sort the locks consistently.

9:57 jcromartie: I want to implement a parser to turn whitespace and indentation into sexps... like Logo syntax

9:57 AWizzArd: (locking [db1 db2] ...) you mean?

9:57 jcromartie: not to do general programming in, but for things like config files

9:57 AWizzArd: jcromartie: look at fnparse

9:58 Efficiency-wise the solutions for the transactions are probably all bounded by the sync to disk anyway.

9:58 rsynnott: assuming that you actually force sync-to-disk, of course

9:58 some people consider OS buffering to be sufficient

9:59 (or have battery-backed writeback cache which actually works)

9:59 AWizzArd: rsynnott: yes, i mean forcing data to disk

9:59 rsynnott: and assuming that your operating system takes notice of you forcing a sync ;)

10:00 AWizzArd: This can be done with a FileChannel via .force

10:00 or, as hiredman pointed out, with java.io.FileDescriptor’s .sync

10:01 rsynnott: if the disk or the OS are lying, then no db system can be used safely on such a system

10:01 * rhickey is tired of boxed numbers

10:01 AWizzArd: rsynnott: I will just forward the lie :-)

10:01 rsynnott: AWizzArd: indeed :)

10:01 and yet, the disk and/or OS often are lying

10:01 AWizzArd: rhickey: why does Su.. Oracle not change it in Java 7?

10:02 rsynnott: there are various articles out there on how to make very sure they're not

10:02 rhickey: AWizzArd: change what?

10:02 AWizzArd: support for boxed numbers

10:02 rsynnott: (though depending on perspective use of a proper write-back cache might or might not be considered a lie in that case)

10:03 AWizzArd: sbcl is using some nice tricks

10:03 to calculate with native numbers

10:03 rhickey: the tricks are old and well known

10:03 chouser: the total amount of effort required in the compiler, type "system", collections, etc. to support primitives is daunting

10:03 rhickey: but there's no motivation for Java since it has primitives

10:04 * AWizzArd sighs

10:04 rhickey: chouser: but are primitives wrong? they are what the hardware can actually do

10:04 Lisp Machines RIP

10:04 no tagged numbers in hardware

10:05 chouser: whatever requires the most work is wrong. :-)

10:05 rhickey: and if tagged numbers could only ever be 1/100th as fast?

10:05 AWizzArd: rhickey: is there any eta on Cells?

10:05 chouser: Java doesn't support primitives for its own collection types, does it?

10:06 other than array of course

10:06 I guess what I mean is, do Java generics support primitives?

10:07 rhickey: they don't. but .Net generics do

10:07 chouser: C++ templates do, but again, is it worth the complexity cost?

10:07 cemerick: rhickey: but don't they just get boxed in .NET anyway?

10:07 rhickey: cemerick: no

10:08 true generics over value types

10:08 packed representation

10:08 chouser: but not using type erasure, right? does that complicate things for Clojure support?

10:08 cemerick: that was my impression from some time ago

10:08 rhickey: chouser: yes, much more complex. But the question is, can you do without primitives without driving everyone back to C++?

10:09 i.e. could Java do without primitives?

10:10 all industrial strength CLs also have untagged full-width fixnums and unboxed floats, with commensurate grief and incompatibility

10:10 because not being able to reach the hardware is death

10:10 chouser: It does seem likely that might shrink its user base. But I have so rarely written any code (except actually inside the kernel) that demands enough performance from math that it would matter at all.

10:11 cemerick: yeah, same here

10:11 rhickey: heh, but you both rely on code that does

10:12 * rhickey looks at PersistentVector.tailoff

10:12 cemerick: eh, actually, there's a big hunk of matrix stuff I wrote years ago that I *still* depend on :-P

10:13 rhickey: doesn't this largely go away once IFn.invoke has float and double overloads?

10:14 rhickey: long and double args returns, yes, but that's primitive support

10:14 also move to non-objectifying math

10:14 _fogus_: Up until a couple years ago most of what I did was pretty dependent on fast math. These days not so much

10:15 rhickey: i.e. long arithmetic that throws on overflow rather than convert to reference type

10:15 if you use Clojure vectors you depend on fast math

10:15 cemerick: The real kicker is that it's way, *way* cheaper to spin up 2x, 10x nodes on ec2 than stress too much about perf

10:16 I may think differently once the baseline changes. :-)

10:17 rhickey: if Clojure doesn't get these things then some code will always have to be written in Java

10:18 AWizzArd: One CL guy implemented a type of neural networks (Boltzmann Machine) and used arrays to represent his matrix. Those arrays are huge and eat very much RAM. He needs mutable arrays for this because he does not want to have two big arrays in RAM at once, and it is probably faster to mutate array cells than calculating up a full new Vector.

10:18 cemerick: rhickey: post a couple inflammatory messages comparing clojure to ocaml or something under an alias, and everyone will get revved up. :-)

10:19 _fogus_: ocaml is the fastest language evar! (or so I've read)

10:20 * angerman wonders how much of that speed will be left once his next semester project of implementing ocaml in scala is done

10:20 cemerick: yeeouch

10:20 rsynnott: cemerick: even cheaper now; did you see their spot pricing thing?

10:21 (you can bid on spare capacity)

10:21 cemerick: rsynnott: yes, I'm aware of it, though I haven't researched it. I will before we go to production, tho.

10:21 'course, just how much spare cap is there anymore ;-)

10:25 te: damn you ocaml with your tail recursion

10:27 jcromartie: te: what about it? clojure has recur

10:27 cemerick: I quite love recur vs. "unbounded" tail recursion

10:29 AWizzArd: recur is easily searchable and allows for anon functions that can do recursion, without requiring the y-combinator.

10:30 _fogus_: Haven't had too many chances to whip out the Y, even before recur

10:30 Chousuke: I wonder if it would be possible to implement a recur-like construct for mutual recursion :/

10:31 something like (recur-at somefunc args)

10:31 jcromartie: recur is nice :) it does what it says on the tin

10:31 jasapp: I've never end up using mutual recursion much

10:31 AWizzArd: Chousuke: you don't talk about trampolines right?

10:31 somnium: Chousuke: maybe a case statement with function names and pass [& args] to the right one?

10:32 Chousuke: AWizzArd: no, I mean a real recur form, except that it supports a target

10:33 I think I would prefer one to having a TCO guarantee

10:33 somnium: (loop [fnname args] (case :foo ... case :bar))

10:33 Chousuke: somnium: I don't think that's what I want :P

10:34 te: Chousuke: there's a trampoline isn't there?

10:34 Chousuke: yeah, but it's not very convenient to use :/

10:35 somnium: Chousuke: a macro could make it more magical tco-ish, I wonder if it would offer any performance benefit for hordes of tailcalls

10:37 rhickey: (definterface IName

10:37 [foo [int int String] int])

10:37 or

10:37 (definterface IName

10:37 (foo [int int String] int))

10:38 _fogus_: (foo +1

10:38 rhickey: or

10:38 (definterface IName

10:38 (#^int foo [#^int x #^int y #^String s]))

10:39 te: the 2nd one

10:39 i take that back

10:39 the 1st one

10:39 chouser: should match defprotocol, right? so (foo or (#^int foo

10:40 I vote (foo^int [x^int y^int s^String])

10:41 rhickey: the more I see the trailing ^type the less I like it

10:41 chouser: :-(

10:41 rhickey: (definterface IName

10:41 (^int foo [^int x ^int y ^String s]))

10:42 Chousuke: hm, removing the # really does make it cleaner :/

10:42 te: [int [int int String] foo]

10:42 _fogus_: I'm always partial to these types of layouts: (foo [x y x] {x int, y int, z String, :ret int}) but it's a departure

10:43 te: there is something more concrete about []'s

10:43 chouser: I don't know about losing the method name from the first word in the list

10:45 te: id like to respectfully change my vote back again to (foo [int int String] int)

10:46 chouser: I guess protocols will never need types for args or return?

10:48 rhickey: chouser: only if long/double arg/return support is added

10:49 chouser: defprotocol uses (foo [x] [x y]) so should defintereface as well?

10:51 (foo [^int x] int [^int x ^String s] String) ? or do all bodies have the same return type?

11:01 alexyk: liebke: how do we save a dataframe to disk so it could be read by R? :)

11:01 liebke: alexyk: save

11:02 alexyk: ok

11:02 I resorted to PDF'ing in R for now

11:02 need tick names, etc.

11:04 but that's not to say the charts are not pretty on screen! :)

11:39 * _fogus_ heads home to prepare for the snowpacalypse

11:41 jasapp: is there another one coming?

11:42 jkdufair: where are you, fogus? ours has started here in Indiana, USA

11:50 chouser: jkdufair: not here. are you in Indy?

12:04 AWizzArd: chouser: one thing did not get through, from about 2 hours ago. You said: “if you do want to support a transaction on multiple dbs, you'd just list them all in the same form so that it could sort the locks consistently”.

12:04 Then I asked if you mean something like (locking [db1 db2] ...) by that.

12:05 chouser: AWizzArd: sorry, didn't see that. Yes, that's what I mean. rhickey mentioned something similar for cells

12:07 AWizzArd: chouser: yes, this is an advantage of locks. I could order them by the DBs internal id.

12:07 advantage here of locks over the agent approach

12:08 hiredman: rhickey: http://gist.github.com/295631 jop is a special form that allows for directly calling java operators (+,-,*,etc), I picture it as being at the bottom of a protocol that takes care of all the dispatch like Numbers.java, would you be interested in a patch?

12:10 that might be kind of premature since I haven't figured out what the eval() method on an Expr does yet

12:10 chouser: ~scopes

12:10 clojurebot: Gabh mo leithscéal?

12:10 chouser: ~scope

12:10 clojurebot: scope is at http://paste.lisp.org/display/73838

12:21 arohner: here's a problem I'm having trouble converting into a purely functional implementation

12:22 I have two seqs of items, and I have a predicate I need to call on all combinations of items from the seq

12:22 chouser: ,(for [a (range 4), b (range 4)] (= a b))

12:22 clojurebot: (true false false false false true false false false false true false false false false true)

12:22 arohner: but if the predicate returns true, one of the items doesn't need to be compared again

12:23 and the not comparing is important, because this is an expensive operation

12:23 if (pred a b) returns true, b doesn't need to be in any comparison after that

12:23 is there a way to do this without refs/atoms?

12:23 chouser: yes!

12:24 it's just a matter of figuring out how. ;-)

12:24 what do you want returned?

12:25 arohner: the set of items for which (pred a b) did not return false

12:25 a little more background

12:26 both lists are identical, I'm just comparing the individual items

12:26 and this is original adapted from an algorithm that sets the return value to the input list, and removes items as it goes along

12:26 chouser: ,(map (fn [a] (some #(when (= a %) [a %]) (range 4))) (range 4))

12:26 clojurebot: ([0 0] [1 1] [2 2] [3 3])

12:28 chouser: oh, I see -- once 1 has participated as either arg in a successful predicate, you don't want it included as either arg ever again.

12:28 hmm...

12:30 arohner: it's not either arg, it's the second arg

12:31 if (pred a b) is true, b should not be included ever again

12:32 chouser: ok, the one I gave above does: if (pred a b) is true, no (pred a ...) will never be tested again (which is right, right?) but (pred? b ...) will (which is wrong, right?)

12:43 arohner: I can generate the combinations, and then pass those to a recursive function

12:43 you'd have to filter the pairs each time you want to "remove" an item

12:43 chouser: but once you generate the combinations, you've lost useful info about which ones can be skipped

12:44 arohner: I was thinking: 1) generate all possible pairs, pass them to a recursive function

12:44 run (pred a b)

12:44 remove the first item from the list

12:44 if (pred a b) is true, run filter on the generated pairs, and recurse

12:45 chouser: if (pred 1 2) is false, you still want to check (pred 2 1), right?

12:45 mabes: How do I have a macro take a symbol and then use that symbol as a suffix for a function that gets defined?

12:46 chouser: and were my previous statements correct?

12:47 mabes: For example, I can define I macro that defines a fn: (defmacro square-fn [fn-suffix] `(defn ~fn-suffix [x#] (* x# x#))) But in this example I would like to have square-"fn-suffix" defined

12:48 chouser: arohner: this doesn't have to be lazy, does it?

12:48 arohner: chouser: no

12:48 if (pred 1 2) is false, you still want to check (pred 2 1)

12:48 http://gist.github.com/296026

12:48 chouser: ,`(defn ~(symbol (str "foo-" 'bar)))

12:48 clojurebot: (clojure.core/defn foo-bar)

12:49 chouser: arohner: are you content with that?

12:49 mabes: arg.. I was looking for that! I thought it would by called sym. Thanks chouser

12:49 chouser: mabes: np

12:49 arohner: I think so

12:49 I don't know how much better it can get

12:49 doesn't seem like much

12:50 chouser: arohner: remove is doing another O(n) pass, but if the expense is 'pred' and not the size of myseq, then you should be fine.

12:50 arohner: right

12:51 chouser: thanks!

12:51 chouser: I think your 'for' is missing something. or something.

12:51 arohner: yeah, that was typed out hastily into the browser

12:51 I'm too used to paredit

12:52 chouser: to avoid that O(n) scan I was trying to uses sets, but it's a bit of a pain.

12:54 arohner: chouser: actually, two sets isn't that bad

12:55 one for the winners, and one for the losers

12:55 check if either item of the pair is in the losers set

12:55 if a value loses, remove it from the winner set and add to the loser set

12:56 when the pairs list is empty, return the winner set

12:57 chouser: thanks again

13:25 alexyk: is there something like ->, but working right to left? I have a data structure and access like,

13:25 ,(let [m {:a {0 "a", 1 "b"} :b {4 "z", 1 "c"}}] ((m :a) 1))

13:25 clojurebot: "b"

13:25 alexyk: as you see, I start with the data structure m, and then fetch keys from nested maps. I guess I can do get-in... but still

13:25 something like <- would be cute

13:26 jkdufair: doesn't ->> work right to left?

13:26 alexyk: not in this case

13:26 here, the keys would go into function positions and cause Clojure swearing like a sailor

13:27 cause they're not all keywords, and can be strings or ints

13:27 jkdufair: how would you access it with <-

13:27 ?

13:29 alexyk: the idea is to put the result into the first position, of a function; since it'll be a map

13:29 or an array

13:30 the fixed things go into second, to look things up

13:30 jkdufair: ah!

13:30 alexyk: (<- m k1 k2)

13:30 jkdufair: seems like it's be easy to implement as a macro

13:30 alexyk: yeah :)

13:30 but I'm new to macros still

13:31 somnium: http://paste.pocoo.org/show/174299/

13:31 jkdufair: me too in a practical sense. but if you look at the code for -> and ->> they are very straightforward

13:31 somnium: ^^ it is :)

13:31 jkdufair: wow. this channel is like the north pole

13:32 somnium: not as general as it could be, may prefix-> or smthing

13:34 alexyk: wow that was quick! thx somnium

13:34 I like <- though

13:36 somnium: alexyk: all these -> <- >>= make it look (sort of) like haskell-in-parens

13:37 I would go with <--(>_<)--<< but as you like :)

13:37 alexyk: somnium: well, haskell in parens is better than one without parens! :) all those stupid $ for precedence

13:37 somnium: you drew an arrow through a pokemon there :)

13:38 nuba: hahaha

13:41 * alexyk vaguely remembers seeing a haskell with lisp synax already... liskell

13:42 alexyk: http://blog.clemens.endorphin.org/2009/01/liskell-standalone.html

13:43 http://clemens.endorphin.org/ILC07-Liskell-draft.pdf

13:58 liebke: (mean []) is NaN, but median is 0.0?

14:01 liebke: alexyk: because you're getting a divide by zero error for mean, but not median. That's the underlying pcolt library

14:01 alexyk: ah ok

14:05 I'm using code like: (let [x ... y ...] (when (and x y) [x y])). Can I simplify it via with-let, or with-let is only for a single binding?

14:11 Chousuke: single bindings only

14:11 and I guess you mean when-let :/

14:12 fdaoud: ,(doc when-let)

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

14:13 somnium: alexyk: a good opportunity to write 'and-let :) (the source for when-let is quite concise)

14:17 the-kenny: just a small macro which expands to nested when-lets :)

14:19 Chousuke: hmm... (defmacro and-let [bindings & body] (let [names (map first (partition 2 bindings))] `(let ~bindings (when (and ~@names) ~@body))))

14:20 no support for destructuring, but oh well

14:20 I suppose you could use (map first (partition 2 (destructure bindings))) :P

14:30 konr: Can I define additional commands to leiningen? In my specific case, I want something like `lein use foo` to generate a foo.jar file containing src/foo.clj

14:31 somnium: http://paste.pocoo.org/show/174331/ << recursive and-let

14:31 konr: *having foo.clj as the main file

14:33 tomoj: konr: you can write plugins

14:33 I don't know how though

14:33 lein-swank is an example

14:34 Chousuke: somnium: that supports only one expression in the body though :/

14:34 avarus: hi

14:35 somnium: Chousuke: ah, easy to fix

14:36 Raynes: konr: In your project.clj, in the defproject, you can do :main ns.of.main.file and then 'lein jar' it.

14:37 somnium: http://paste.pocoo.org/show/174338/

14:37 Chousuke: that was a good catch, thanks

14:38 konr: Raynes: yes, but then I'd have to create a script to change it... it seems that it's not so hard to create a plugin: http://groups.google.com/group/clojure/browse_thread/thread/11ee44e988022289

14:38 Chousuke: somnium: I think you still need a ~@body in the (and-let ...) part as well)

14:38 somnium: 39 :)

14:38 I knew it was coming, copy/paste fail :/

14:39 the-kenny: gist.el in emacs ftw! :)

14:41 somnium: I wonder why assert-args in core is private

14:41 the-kenny: ,(doc assert-args)

14:41 clojurebot: I don't understand.

14:42 Chousuke: that lodgeit pastebin seems better than gist though :/

14:42 since it doesn't require javascript :P

14:42 the-kenny: ,(doc clojure.core/assert-args)

14:42 clojurebot: "([fnname & pairs]); "

14:42 the-kenny: Chousuke: does gist require js? Really?

14:42 Chousuke: last time I checked, yes.

14:43 the-kenny: http://gist.github.com/279651 displays without js here. (please ignore the code ;))

14:43 Chousuke: hm, looks like it does.

14:44 the-kenny: Including gists in other sites doesn't work without js, but simple pasting and viewing ist just plain html

14:44 Chousuke: maybe it's just the blog-embeddable gists that require js :/

14:44 they always throw me off since I usually browse with javascript disabled

14:44 the-kenny: Yes, they use js.. I don't know why

14:44 tomoj: the embeds I saw are just <script> tags

14:44 the-kenny: As far as I understand the code, they don't need to use js

14:49 tomoj: I guess the js makes it so that the latest version will show?

14:49 AWizzArd: So.

15:11 mattrepl: hey nathanmarz, hope you'll post about clojure-cascading hacking =)

15:11 nathanmarz: mattrepl: i absolutely will

15:11 sometime within the next week

15:12 avarus: mhmh...are you guys all hacking on vim or emacs?

15:13 the-kenny: avarus: I think most people here use Emacs

15:13 avarus: hrm...I only need syntax highlighting and some ability to "run" some shellscripts :P

15:14 I'd have to learn the whole emacs stuff for that

15:14 chouser: I use vim

15:14 the-kenny: avarus: Trust me.. if you try slime, you don't want to use shellscripts anymore :)

15:14 avarus: and I guess you are using clojure-mode?

15:14 chouser: last poll there were about as many people using emacs as vim+all other IDEs combined.

15:14 so half, not most. :-)

15:15 avarus: I tried enclojure and the idea plugin for idea

15:15 didn't like it

15:16 I'm normally on linux and using "gedit" :P...but parens highlighting sucks!

15:16 I am currently working on a mac and tried aquamacs which has brilliant parens highlighting

15:16 but no idea if aquamacs is a good alternative to "pure" emacs

15:16 tomoj: aquamacs is perfect

15:17 really easy to set up for clojure, as well

15:17 * the-kenny switched from Aquamacs to plain-old Emacs in Terminal.app

15:17 tomoj: though, learning how to use aquamacs is a different story...

15:17 the-kenny: But Aquamacs is ok, absolutely

15:17 Especially for starters

15:17 tomoj: I mean, you can get away with just treating it like gedit probably (?), but you will be missing out

15:17 somnium: I miss the gmate themes on emacs

15:17 Intertricity: These are a bit of silly questions but, do I need JDK to run clojure? I downloaded clojurebox and it works pretty well

15:18 but I don't know what I could be missing

15:18 somnium: 90% of color-theme.el is border-line offensive

15:18 tomoj: color-theme pissed me off because themes would leave stuff behind and reverting didn't work

15:18 ended up just building my own color theme :/

15:18 chouser: Intertricity: you need JDK to *build* clojure, but only the JRE to use it (including running and compiling clojure code)

15:18 avarus: tomoj: so what? aquamacs or pure emacs? :P I have to learn something nevertheless

15:18 mattrepl: re: aquamacs, gnu emacs has cocoa support now but aquamacs tries to be a good mac app

15:19 tomoj: personally, I use aquamacs on the mac

15:19 I didn't know there was a reason not to

15:19 the-kenny: avarus: Just use Aquamacs. It's Emacs as a nice Cocoa app

15:19 Intertricity: chouser, so I don't even need JDK to compile clojure programs or use api related things like speech synth?

15:19 tomoj: except for use inside screen maybe

15:19 avarus: not using screen here

15:19 chouser: Intertricity: right

15:19 Intertricity: wow nice

15:19 billsmithaustin: Intertricity: that's all in the JRE.

15:19 Intertricity: chouser, thanks :D

15:20 tomoj: avarus: also, I happened to write a blog post the other day about setting up from scratch http://tomojack.com/?p=8

15:20 avarus: ah! :)

15:20 tomoj: that process worked for me in aquamacs

15:20 avarus: great

15:20 tomoj: though you might need to be sure package.el's initialization stuff gets put in the right place

15:20 Intertricity: I used to ignorantly despise java until I saw clojure.. now that little cup icon is pretty to me, hehe

15:21 somnium: anyone used Clojure-CLR with mono?

15:21 Intertricity: somnium, I'm eagerly waiting a binary to play with

15:21 avarus: I'm not

15:22 Intertricity: One more simple question, I don't mind reading if anyone has a link- is there anything specific I need to know about installing new java libraries to use with clojure?

15:22 the-kenny: Intertricity: Just put them in the classpath

15:23 avarus: ya, simple as that

15:23 Intertricity: classpath- this folder? C:\program files\java\jre6\lib

15:23 mattrepl: Intertricity: and there has been some work on a dependency manager, with various libs thrown up on http://clojars.org

15:23 the-kenny: Intertricity: For example, yes.

15:24 avarus: the-kenny: tomoj: mmh...which version are you running? on aquamacs.org there is 1.9 but also 2.0 preview 1 which says it's based on coca

15:24 billsmithaustin: Intertricity: I wouldn't put them there. Better to install them someone outside of the JRE and then add that directory to the classpath. Otherwise you'll have problems when you upgrade your JRE.

15:24 the-kenny: avarus: I used the preview. It's pretty stable

15:24 Intertricity: billsmithaustin, oh I see

15:24 the-kenny: But I'm using a self-compiled recent version now

15:24 avarus: I did "java -cp $MYOWNCLASSPATH ... "

15:24 mattrepl: Intertricity: the classpath can be set when you run the JVM.. `java -cp /some/path:/another/path:a/relative/onetoo ...`

15:25 liebke: alexyk: if you're still around, I created a save-pdf function that writes incanter.charts to a pdf file: https://gist.github.com/b91cc35f1c7c71b7fafe

15:25 avarus: the-kenny: ok, thanks :)

15:25 the-kenny: snow leopard, too?

15:25 the-kenny: avarus: Yes

15:25 avarus: ok :)

15:25 mattrepl: liebke: nice

15:25 technomancy: just as a warning, Aquamacs breaks^H^H^H^H^Hchanges core behaviour in strange and unpredictable ways

15:25 Intertricity: mattrepl, thanks :)

15:25 technomancy: making it difficult for maintainers to target it for compatibility since it's not cross-platform

15:26 neotyk: yep

15:26 avarus: :>

15:26 liebke: mattrepl: yeah, I just used a library called itext, which fortunately is in a public maven repository -- so I can just include it in a project.clj or pom.xml file

15:27 the-kenny: technomancy: Hehe

15:28 technomancy: I try to steer people towards http://emacsformacosx.com/ as much as possible

15:28 avarus: ya, just tell me like that

15:28 I'll have a look

15:28 neotyk: like following code http://clojure.pastebin.com/m3e22d711 will output stuff to *inferior-lisp* buffer

15:29 technomancy: I mean, it's your choice; enough people use aquamacs that some one is likely to find the bugs before you do, but I just thought I'd throw that out there.

15:29 neotyk: and not where you would except that is: slime-repl

15:30 technomancy: this emacsfotmacosx is normal emacs 23?

15:30 how different it is from aquamacs?

15:30 technomancy: neotyk: yeah, it's just a convenient build of the official source tree IIRC

15:30 neotyk: Aquamacs is a fork

15:30 this is GNU Emacs

15:30 neotyk: very nice

15:31 * avarus is unsure about aquamacs now :P

15:31 mattrepl: yeah, cocoa support is in the official repo

15:31 the-kenny: Yeah, there's also Emacs.app

15:31 mattrepl: for more info: http://www.emacswiki.org/emacs/EmacsForMacOS

15:31 * neotyk is taking emacsformacosx for a spin

15:31 technomancy: Emacs.app is just the name for the artifact you get when you compile GNU Emacs 23+ with the OS X flags turned on

15:31 aka "Cocoa Emacs"

15:32 neotyk: how many emacs is there anyway?

15:32 same as linux distros?

15:32 technomancy: neotyk: you don't want to know: http://www.jwz.org/doc/emacs-timeline.html

15:32 the history goes back much further than Linux

15:33 avarus: come on guys...the confusion makes me installing textmate :P

15:34 neotyk: is not that bad though, compared to number of linux distros

15:34 konr: Guys, what is wrong with (with-ns 'foo (println "bar")) ?

15:34 mattrepl: it's really just GNU Emacs (and platform-specific, unofficial ports) and XEmacs

15:34 nowadays, that is

15:34 konr: I get a "no namespace found" error, but should it create one?

15:34 *shouldn't

15:34 tomoj: technomancy: is that what used to be called "carbon emacs"?

15:34 hiredman: ,(doc with-ns)

15:34 clojurebot: "clojure.contrib.with-ns/with-ns;[[ns & body]]; Evaluates body in another namespace. ns is either a namespace object or a symbol. This makes it possible to define functions in namespaces other than the current one."

15:34 tomoj: it looks familiar

15:34 neotyk: like there is no hannah montana emacs fork while there is such a distro: http://hannahmontana.sourceforge.net/Site/Home.html

15:35 technomancy: tomoj: Carbon Emacs was the old official port

15:35 tomoj: ah

15:35 avarus: I so fucking hate hannah montana

15:35 hiredman: ~def with-ns

15:35 technomancy: but it used deprecated OS X APIs, so it was dropped in favour of Cocoa

15:35 neotyk: avarus: the distro? :O

15:35 technomancy: tomoj: Carbon only works with 22, which is several years old

15:35 anyway, it's much simpler outside OS X.

15:35 avarus: neotyk: no :P

15:35 technomancy: just pick a version number =)

15:35 tomoj: I do find myself going through trying to make aquamacs act more like normal emacs

15:35 hiredman: ,(doc the-ns)

15:35 clojurebot: "([x]); If passed a namespace, returns it. Else, when passed a symbol, returns the namespace named by it, throwing an exception if not found."

15:36 hiredman: konr: the doc doesn't say it does, and the code definitely doesn't

15:40 konr: hiredman: thanks!

15:41 Intertricity: hrm, I thought c-c c-c was send buffer? I'm only getting send line

15:41 the-kenny: Intertricity: C-c C-c is compile-defun

15:42 Intertricity: it's only sending one line at a time to the repl for me

15:43 ahh c-c c-k for clojurebox

16:01 BrandonW: hello, does anyone here have the progamming clojure book?

16:01 jasapp: yeah

16:01 BrandonW: I have a question on faux-curry vs partial, and the faux-curry implementation in general

16:02 okay, page 165/166 (on the ebook)

16:02 not sure if it is the same on the paperback copy

16:02 the faux-curry definition seems to behave in exactly the same manner as the partial function. is that true? is that intentional?

16:03 jasapp: it must be on a different page

16:04 I'm not sure, it's been awhile since I've looked at this

16:05 BrandonW: it is in the lazier than lazy sub chapter of the functional programming chapter

16:05 billsmithaustin: In the ebook, page 165 has the heading, "Lazier than lazy".

16:06 It starts right after this code sample: (defn

16:06 count-runs

16:07 "Count runs of length n where pred is true in coll."

16:07 [n pred coll]

16:07 (count-if #(every? pred %) (partition n 1 coll)))

16:07 Sorry for the link breaks.

16:08 BrandonW: okay, it is the page after that

16:15 it's kind of weird

16:15 i can see why the extra apply is needed in the definition of faux-curry

16:15 but i don't quite understand it

16:17 duncanm: is it a design flaw if i'm too aggressive with agents?

16:19 avarus: tomoj: I'm just setting up aquamacs but I fail at the first pasted code where I should press "C-j" :P

16:20 control-j? but where

16:20 if I do it in aquamacs it just makes a new line

16:21 tomoj: ok

16:21 yes, heh

16:21 aquamac's *scratch* buffer was in text-mode by default, forgot about that

16:21 try doing 'M-x emacs-lisp-mode' first

16:22 avarus: ok

16:22 lancepantz: forgive my lack of java-foo, but i get #<Input org.mortbay.jetty.HttpParser$Input@27e91a4d> when i try to println on request :body in compojure

16:22 how can i just print out the request body?

16:22 tomoj: avarus: and lemme know if that works so I can add that to the post

16:22 lancepantz: as a string

16:23 tomoj: C-j is bound to newline by paredit for me :(

16:23 C-x C-e should work

16:24 BrandonW: lancepantz: it looks like it is a stream

16:25 you might have to call the appropriate java stream methods in order to read the data in a string representation

16:25 http://jetty.codehaus.org/jetty/jetty-6/apidocs/org/mortbay/jetty/HttpParser.Input.html

16:25 lancepantz: so in this case, read?

16:26 hiredman: I think compojure depends on a bunch of apache stuff, one of their utility methods might turn it into a string

16:26 BrandonW: probably true

16:26 seems like something that could be easily abstracted away from

16:27 kotarak: maybe it has a toString method?

16:27 hiredman: kotarak: I image the representation he is seeing is the toString

16:28 lancepantz: well, (println (.read (request :body))) prints 123, which is not the body

16:28 BrandonW: yeah, it looks like the only way to read the bytes through the java interface is via integer values that would have to be converted into string representation

16:28 read only reads one byte

16:28 lancepantz: jesus

16:28 i hate java

16:28 BrandonW: well not byte actually

16:29 oh nevermind

16:29 you can get one block at a time, or send in a byte array and get back an arbitrary amount of the stream

16:29 avarus: tomoj: that thing is killing me :P..don't think I can contribute anything to that post for now :P

16:29 cemerick: compojure doesn't depend on any apache anything

16:29 what's the issue?

16:30 billsmithaustin: BrandonW: faux-curry is a little different from partial. I'll give you an example.

16:30 avarus: compojure has some libs from apache as deps (for uploads e.g.?!)

16:30 tomoj: avarus: didn't work?

16:30 lancepantz: cemerick: i'm just trying to println on a request, so i can look at it for debugging purposes

16:30 cemerick: yeah, optional though

16:30 BrandonW: lancepantz: you may be able to use somethign from duck-streams contrib

16:30 cemerick: lancepantz: from within a handler, I presume?

16:31 lancepantz: yeah

16:31 cemerick: (println request)

16:31 hiredman: you can use http://paste.lisp.org/display/93138 to turn an input stream into a bytebuffer

16:31 avarus: tomoj: sure, I clicked somewhere and activated the emacs lisp mode and I could again click in some context menu to evaluate the code and something happened :S

16:31 tomoj: you should be good, then

16:31 hiredman: cemerick: compojure sure comes with a lot of the apache commons libraries

16:31 for something that doesn't depend on them

16:31 tomoj: if 'M-x package-list-packages' now works, you're good

16:31 billsmithaustin: Try ((faux-curry + 1 2 3)) vs ((partial + 1 2 3))

16:31 avarus: tomoj: wouldn't it be better to first learn some "pure" emacs first? I feel so list in that :)

16:32 lost*

16:32 hiredman: a bytebuffer can be turned into an array of bytes, and the constructor for String takes an array of bytes

16:32 tomoj: learning emacs can't hurt

16:32 alexyk: to the tune of "unbreak my heart": unclog my repl! My repl grows steadily to hold 30gb out of 31.5gb allotted. Things are slow as it gc's all the time. DIs it just the (def x ...) vars I created? If I do (def x nil) for some, should it get better? Is there a way in JVM to do a crude sizeof(x)?

16:32 tomoj: aquamacs is not all that different for the basics

16:32 alexyk: cemerick: don't you do a PDF library?

16:33 tomoj: but yeah, switching to pure emacs wouldn't be a bad idea

16:33 cemerick: hiredman: I *think* the file upload/multipart stuff is the only dependency, and optional if you're not doing uploads. *shrug*

16:33 alexyk: It's what we're known for, yeah: http://snowtide.com

16:33 hiredman: cemerick: it also has commons codec and io

16:33 tomoj: (oh, I misunderstood you I think. but yeah)

16:33 lancepantz: (println request) still prints the body as HttpParser$Input

16:34 alexyk: cemerick: 'cause I just saw iText liebke used to PDF-ize the Incanter charts and was wondering where's your pro bono contribution to the OSS movement or something! :)

16:34 avarus: I'll try http://emacsformacosx.com/, tomoj :)

16:34 BrandonW: billsmithaustin: i understand that the faux-curry doesn't evaluate the function even if it has all the required args because clojure can't know in advance if the user is done sending args toa function, so you need to evaluate the function twice to retrieve the result

16:34 cemerick: alexyk: we don't generate PDFs, we extract content + data from them :-)

16:34 BrandonW: but i don't quite understand why

16:34 tomoj: avarus: hopefully the instructions in the post should work perfectly there, when you're ready

16:34 itistoday: is there a way to precompile .clj files to .class files?

16:35 alexyk: cemerick: ah, now I am deconfused. in , not out

16:35 BrandonW: i can kind of see the importance of applying partial to itself before beginning to apply the arguments to the resulting function

16:35 lancepantz: http://www.pastie.org/811705

16:35 avarus: oh, too bad, the download doesn't work at that website :>

16:35 BrandonW: but i don't quite understand why leaving the first 'partial' out prevents the faux-curry from working

16:35 lancepantz: i want to see the body as a string

16:35 alexyk: cemerick: do you determine structure: tables, hierarchy?

16:35 avarus: it redirects me to the main website: http://emacsformacosx.com/

16:35 itistoday: like say if you have two .clj files in a directory and they call code from each other, how would you run that from the command line?

16:35 arohner: itistoday: yes, http://clojure.org/compilation

16:35 kotarak: itistoday: http://clojure.org/compilation

16:36 tomoj: avarus: hmm, when I click download a dmg tries to download

16:36 cemerick: alexyk: Yes, in many circumstances. We're currently working on something that is generally-applicable, and outrageously accurate and absurdly configurable.

16:36 avarus: oww..the world hates me today :)

16:36 cemerick: and can be applied to any file type

16:36 technomancy: itistoday: you can also use clojure.main

16:36 tomoj: cemerick: just curious then, did you investigate tika?

16:36 itistoday: technomancy: how?

16:36 alexyk: cemerick: can it also regrow hair and obtain models?

16:37 itistoday: technomancy: just specify both of the files?

16:37 kotarak: ,(doc compile)

16:37 clojurebot: "([lib]); Compiles the namespace named by the symbol lib into a set of classfiles. The source for the lib must be in a proper classpath-relative directory. The output files will go into the directory specified by *compile-path*, and that directory too must be in the classpath."

16:37 technomancy: itistoday: java -cp /path/to/clojure.jar:/path/to/your/project/src clojure.main -e "(use 'my-project) (invoke-my-projects-function)"

16:37 avarus: tomoj: oh great, I'm downloading it 15 times now lol

16:37 tomoj: haha

16:37 technomancy: itistoday: not exactly what I'd call convenient

16:37 most people write bash wrappers

16:38 * alexyk wonders, it's 4:30+ pm Eastern and this place is a-scrollin'. Do these people go home, or are there already?

16:38 cemerick: tomoj: briefly, it's not particularly interesting, IMO

16:38 alexyk: cemerick: I know a business interested in detecting the hierarchy, with an end-user product for PDF conversion.

16:38 itistoday: technomancy: right, 'clj' etc. this is actually a question someone asked on the mailing list that i'd like to answer for them, but I've been bad and haven't even attempted to reproduce this because of how little clojure coding i've done. thanks for the answer! i'll pass it along

16:38 tomoj: cemerick: ok, I just discovered it and haven't looked at any details

16:39 I guess our requirements probably don't match anyway

16:39 cemerick: alexyk: send them our way, we might be able to help

16:39 BrandonW: alexyk: that is an interesting question. i wonder if you could correlate activity in this irc channel with data on who is in here, what time zone they are in, if they are using clojure in the workplace, or in their own time at home

16:40 cemerick: tomoj: it's fundamentally content-oriented, which is OK, but not up to snuff for structured data extraction

16:40 tomoj: sounds perfect for me then :D

16:40 cemerick: yeah, tons of useful things you can do with it

16:40 tomoj: BrandonW: based on when they're working?

16:40 arohner: chouser: I came up with a new arrow trick. You've probably already thought of it, but it amuses me

16:41 (-> (fn [x] ...) (reduce my-seq))

16:41 tomoj: I'm in here during work hours all the time, but hardly ever actually using clojure at work :/

16:41 alexyk: cemerick: sure, will forward the idea (they are on .NET and may be doing it in-house in some G-dawful Y# thing though)

16:41 cemerick: tomoj: our aim is to be able to take any document type (invoice, resumé, financial disclosure, tax form, the federal register, etc etc), a configuration, and have fundamentally database-ready data flow out.

16:42 alexyk: PDFTextStream.NET is available :-)

16:42 tomoj: sounds... fun

16:42 alexyk: cemerick: did you see the guy with OCaml PDF ported it all into F# too?

16:42 cemerick: alexyk: no, link?

16:43 alexyk: hold on

16:44 http://www.coherentpdf.com/ -- and ocaml code exists as a literate book

16:44 I bet you can translate ocaml into clojure almost literally or programmatically

16:44 BrandonW: tomoj: yeah. you'd have to assume a lot about average working hours, but it would be an interesting experiment to graph the activity of this channel and try to infer things from it

16:45 tomoj: yeah

16:45 BrandonW: i'm here usually during work, but same as you

16:45 i'm learning it at home

16:45 tomoj: even just looking at the activity patterns would interest me

16:45 BrandonW: but occasionally at work i will read up on the pdf and try stuff out

16:45 alexyk: let's start with metadata "I'm at work pretending to work" or "I'm at home working from home", etc. :)

16:45 BrandonW: then i come here with my questions on currying :)

16:45 alexyk: then some powerful machine learning will be running in Incanter!

16:46 we need volunteers to tell us their true status at all hours of the day

16:46 hiredman: asking for the truth is cheating

16:46 tomoj: I have only gotten to use clojure at work for a couple days, and I've been doing that in the middle of the night

16:46 alexyk: hiredman: ground truth is necessary for the training data

16:46 hiredman: you must use statistics to determine it

16:47 tomoj: is the ml stuff in incanter now? :D

16:47 avarus: I want to use clojure for a project at work so I'm the only one able to master it :P

16:47 BrandonW: we will actually have the freedom to use clojure at work, once we finish our initial re-implementation of everything that we inherited (in C#)

16:47 alexyk: hiredman: statistics cannot pull ground truth out of, well, air

16:47 avarus: so I will be at least :P

16:47 kotarak: I seem to be the only one to be knocked out by corporate firewall. :/

16:47 BrandonW: unfortunately my co-worker is a bit more enamored by scala (but that is mostly because of lift)

16:47 tomoj: I got an e-mail from a co-worked about lift the other day.. ignored it

16:47 avarus: I learned scala...it's a big language imho

16:47 BrandonW: yeah

16:48 * the-kenny will have this freedom too :)

16:48 BrandonW: it will be better than java and C#, and i think i would like it more than python/ruby

16:48 avarus: I like "simple" and light languages

16:48 BrandonW: but i definitely am leaning towards clojure. compojure just isn't quite as far along as lift is

16:48 (in terms of convincing my co-worker :D)

16:48 tomoj: I think that's on purpose, though

16:48 avarus: I don't like lift because it puts me quite in a straight jacket

16:48 BrandonW: yeah

16:49 yep

16:49 i only just realized the other day

16:49 alexyk: as I said earlier on #scala: Scala. She was a strict, bossy bitch. Clojure: he was a bad-ass drifter. Together, they had to fight the Java mob.

16:49 tomoj: so those of us that want more need to build it on top of compojure I suppose

16:49 BrandonW: how easy it is to implement authentication/authorization in compojure

16:49 avarus: alexyk: hehe

16:49 tomoj: BrandonW: really? I've been thinking about that

16:49 BrandonW: at first i thought it was funky that it was left out, then i realized it really is only 30 or so lines of code, and you can completely customize it then

16:49 tomoj: BrandonW: just basic user/pass auth?

16:49 somnium: it seems compojure is trying to dissolve into an library for ring so someone else can write liftjure or whatever

16:49 BrandonW: the example from the compojure wiki

16:49 well not necessarily basic

16:50 but that's where customization comes in

16:50 tomoj: ah, I need to write an oauth provider :/

16:50 BrandonW: it is really easy to just grab a value from a form for user/pass, auth it against database/xml/hardcoded values, etc

16:50 and then store it in a cookie via jetty

16:50 avarus: tomoj: I already spotted a lib for oauth in clojure

16:50 at github

16:50 tomoj: probably client only, I bet

16:50 avarus: ya

16:51 ah "provider"

16:51 missed it :)

16:51 itistoday: ok i'm actually trying this myself now, i've got two clj files, both of them seem to specify the same namespace but the files obviously have different names

16:51 BrandonW: i didn't realize jetty takes care of all the cookie information for you, which is great. you just add the information about how the user is authenticated to the session, and everything is taken care of for you

16:51 somnium: alexyk: :) what was the reaction to that comment?

16:51 tomoj: BrandonW: what exactly do you mean?

16:51 itistoday: foo.clj and foo-utils.clj, how do i run them using the typical 'clj' shell script?

16:51 tomoj: my cookie code doesn't care about jetty

16:51 BrandonW: basically, i didn't realize that compojure doesn't need to implement cookie handling of authentication; that jetty does it for you

16:51 oh

16:52 itistoday: he/I are obviously not using the ns/use/require functions correctly

16:52 tomoj: hmm, strange

16:52 BrandonW: maybe i mis-read the wiki

16:52 let me load it up

16:52 tomoj: nah, you're probably right

16:52 compojure is still largely mysterious to me

16:52 itistoday: want to just be able to do: clj foo.clj

16:53 does foo-util.clj have to be in a different namespace?

16:53 avarus: I asked the other day what template engine I can use and some said "compojure". I realized it doesn't have such a thing...only (html [:h1... etc...

16:53 itistoday: it has a single function defined in it that's called from foo.clj

16:53 tomoj: BrandonW: link, though?

16:53 itistoday: avarus: use gulliver

16:53 tomoj: avarus: enlive is an option

16:53 BrandonW: http://ericlavigne.wordpress.com/2009/01/04/compojure-security-authentication-and-authorization/

16:53 itistoday: enlive doesn't let you do PHP-style templating

16:54 tomoj: good

16:54 :P

16:54 itistoday: tomoj: it's not

16:54 avarus: itistoday: I'll have a look, thanks

16:54 itistoday: i mean, it's useful sometimes to do it the enlive route, but for example if you're serving "static" pages, like a homepage, it's not good

16:54 tomoj: designers hate it

16:55 avarus: http://www.brool.com/index.php/a-modest-proposal

16:55 now, if someone can help me with this damned newbie question

16:55 there should be a page somewhere that tells you how to run two .clj files from the command line

16:55 it's like clojure 101

16:56 BrandonW: tomoj: read that page i linked, then look at the comment from James, jan 5th 2009 6:27 PM

16:56 tomoj: itistoday: why would designers hate it? I'd think it'd be better

16:56 BrandonW: starts with "Jetty uses an in-memory session store..."

16:57 Chousuke: tomoj: that's my impression too

16:57 tomoj: they can just make a static html page which they can view in their browser locally

16:57 itistoday: tomoj: yes, if that's all they want to do

16:57 tomoj: ah, I see

16:57 itistoday: but usually designers want to be able to do the equivalent of PHP's include()

16:57 tomoj: so, designers that want some access to code stuff but don't want to deal with enlive?

16:57 itistoday: tomoj: yes

16:57 tomoj: ah, yeah

16:58 you could probably hack that in, but, yeah

16:58 itistoday: that's really all they want, to use include so they don't have to change code in 20 million places

16:58 Chousuke: well, you could use a placeholder element for that..

16:59 tomoj: I haven't figured out layouts/subtemplates with enlive yet

16:59 BrandonW: I'm confused by that

16:59 itistoday: so here's what the guy posted to the mailing list: http://paste.pocoo.org/show/174385/

16:59 kotarak: tomoj: simply functions

16:59 tomoj: BrandonW: there's no with-session

16:59 itistoday: i'm guessing he's using 'require' incorrectly

17:00 Chousuke: But I think designers would like to be able to write a template which has placeholder elements that will be replaced and modified by systems like enlive :/

17:00 itistoday: ,require

17:00 clojurebot: #<core$require__6458 clojure.core$require__6458@1eed1e1>

17:00 itistoday: ,(doc require)

17:00 clojurebot: "([& args]); Loads libs, skipping any that are already loaded. Each argument is either a libspec that identifies a lib, a prefix list that identifies multiple libs whose names share a common prefix, or a flag that modifies how all the identified libs are loaded. Use :require in the ns macro in preference to calling this directly. Libs A 'lib' is a named set of resources in classpath whose contents define a library of Cloju

17:00 kotarak: itistoday: require must be load

17:00 tomoj: maybe he is doing sessions in some other way besides using compojure's session middleware?

17:00 kotarak: itistoday: the ns in foo-utils must be in-ns 'foo

17:01 alexyk: somnium: I'm using both clojure and scala and promote world peace in general, so folks take it the right way

17:01 Chousuke: perhaps you could have a simple preprocessor for such templates that allows for includes or some other simple manipulations

17:01 tomoj: my understanding was that the choice of where to put the session is made when you wrap the with-session middleware, not by jetty

17:02 BrandonW: tomoj: i'm not fluent in compojure at all at this point, but it looks like his login-controller method takes in a session & params, alters teh session by adding the user's authenticated name to the dictionary of session key/vals

17:02 itistoday: kotarak: here's where i am now: http://paste.pocoo.org/show/174387/

17:03 tomoj: yeah, I just don't understand where the session ref comes from in the first place

17:03 itistoday: kotarak: still getting an exception :-p

17:03 BrandonW: and then at that point, the plaintext name/val of the authenticated user would be stored in memory on the server, and the cookie would have a securely random key pointing to that piece of data

17:03 kotarak: itistoday: because you obviously don't load foo-utils: (ns foo (:load "foo-utils"))

17:03 BrandonW: so then jetty takes care of cookies for you, and all you have to worry about is the act of authenticated the user (which is easy)

17:04 tomoj: I guess either compojure has changed since that was written or there's some sessions-without-with-session feature.. did you try running that code?

17:04 BrandonW: no

17:04 haven't even finished learning clojure at this point

17:04 tomoj: oh well, in any case, you're right, it's easy :)

17:04 arohner: the default session handler is in-memory

17:04 I believe it's a middleware

17:04 itistoday: kotarak: thanks! that's what i was missing, because I had no idea. :-p

17:04 tomoj: arohner: yeah, that was my understanding

17:04 BrandonW: but what i'm thining is it doesn't really even matter exactly what compojure can or can't do, unless you're saying compojure doesn't allow you to add variables to the session?

17:04 arohner: but yes, you can replace session handling with e..g a database if you want

17:04 tomoj: looking at code that is using sessions without with-session somehow

17:04 BrandonW: *thinking

17:05 tomoj: BrandonW: I'm saying there is no session at all unless you use with-session

17:05 itistoday: kotarak: you know, i'm looking on the clojure site and i don't see this documented anywhere

17:05 arohner: but compojure by design has no dependency on a database

17:05 tomoj: and in that case, compojure sends the cookies and manages the sessions in memory

17:05 arohner: that's higher up the stack

17:05 BrandonW: hmm

17:05 by manages the cookies, you mean it doesn't let jetty do it automatically?

17:06 tomoj: well, jetty sends the cookies to the browser

17:06 but compojure builds it

17:06 "Set-Cookie: compojure-session=...." or something like that

17:06 BrandonW: interesting. yeah i'll have to play around with it once i get to that point

17:07 tomoj: and you could swap out jetty with whatever and it would work the same

17:07 BrandonW: i have a couple smaller projects i want to use clojure for first, but after that a web site is my primary goal.

17:07 kotarak: itistoday: well, you have to leave something to the gurus to shine. ;)

17:07 tomoj: I think it's a good idea to wait a while before tackling compojure

17:07 BrandonW: why?

17:07 clojurebot: http://clojure.org/rationale

17:08 BrandonW: in terms of clojure experience? or waiting for the api to be more stable?

17:08 tomoj: well, I was thinking the former

17:08 BrandonW: this is my first foray into functional programming AND in a lisp variant

17:08 tomoj: but compojure is getting refactored, so the latter is relevant as well

17:09 well, good luck :)

17:09 BrandonW: i definitely feel like i'm living in flatland trying to comprehend 3 dimensions, sometimes (to rip off carl sagan :))

17:09 tomoj: I seriously watched that video earlier today

17:09 somnium: flatland is a great book :)

17:10 technomancy: BrandonW: that would be 4 dimensions then. =)

17:10 tomoj: (and downloaded cosmos :D)

17:10 BrandonW: yeah i have cosmos on my netflix. haven't watched it yet though

17:10 alexyk: hmm -- my manual clojure repl starter doesn't load the user.clj in the current dir. Is it the job of the clojure.main?

17:10 BrandonW: just rented contact and watched that again. that movie is very different from when you were like 13, to when you're 25... haha

17:11 hiredman: alexyk: is . on your classpath?

17:11 user.clj is loaded from the classpath

17:11 alexyk: hiredman: qed, thx

17:14 BrandonW: okay so i still don't quite understand faux-curry from programming clojure, if anyone wants to take a stab at helping me before i go home :D

17:15 (defn faux-curry [& args] (apply partial partial args))

17:15 avarus: do you have to?

17:15 BrandonW: is the only reason to apply the partial function to itself, so that you end up with something that needs to be evaluated twice in order to obtain the result at the end?

17:16 no, but it seems like one of the things that if you don't understand it, it limits your power within the functional paradigm

17:16 and i like having power :D

17:16 avarus: ok :)

17:16 alexyk: hmm: I had in my user.clj, (set! *print-length* 42), and upon launch, repl fails with: Can't change/establish root binding of: *print-length* with set. But I can do it once the repl is up manually. ?

17:16 somnium: BrandonW: theres always monad tutorials :)

17:16 BrandonW: yeah i'll wait a bit on those :)

17:17 stuart halloway does frequent this channel, right?

17:18 that would be pretty cool, being explained a concept from the book by its author, heh

17:19 tomoj: (faux-curry + 1) == (apply partial partial [+ 1]) == (partial partial + 1)

17:20 ((faux-curry + 1) 2) == ((partial partial + 1) 2) == (partial + 1 2)

17:20 (((faux-curry + 1) 2) 3) == ((partial + 1 2) 3) == (+ 1 2 3) == 6

17:21 guess it's clearer with just (faux-curry +)

17:23 but yeah, you end up with something that when called returns something that when called returns the answer

17:24 as opposed to (defn faux-curry [& args] (apply partial args)) where you can just do ((faux-curry + 1) 2) and get the answer with one call

17:24 hiredman: tomoj: that is partial

17:24 tomoj: I don't remember that from the book.. seems strange

17:25 yep

17:25 arohner: alexyk: you can only set! bindings when you're already inside a binding for that var

17:25 the repl sets up bindings for *print-length* and a few other things

17:26 user.clj gets loaded "outside" of the repl, so it doesn't work

17:26 alexyk: arohner: so why can I do that one the repl shows me the prompt, but not from user.clj? am I doomed to manually do that?

17:27 arohner: the repl code looks like

17:27 (binding [*print-length* ...] (do-repl))

17:27 when you require from the repl, you're inside do-repl

17:27 i.e. inside the binding for print-length

17:28 alexyk: arohner: (set! *print-lengtn* 42) works fine in repl though

17:28 arohner: right

17:28 you can set! a var, if you're inside a binding

17:28 alexyk: so when does clojure.main read user.clj?

17:28 arohner: not inside the repl

17:28 alexyk: pity

17:29 is the purpose of user.clj to serve the repl, or any old clojure launch?

17:30 arohner: how are you starting clojure?

17:30 tomoj: user.clj has a purpose?

17:30 alexyk: arohner: java ... clojure.main

17:30 tomoj: yeah, it's like .clojurerc

17:31 tomoj: you put it in your home directory?

17:31 alexyk: tomoj: on the classpath

17:31 tomoj: oh, crazy, for adding stuff to the repl?

17:31 I was thinking earlier I wanted to auto-require repl-utils

17:31 alexyk: but, it just let me down, in terms of the crucial failure to set print-length to prevent Britannica from being shoved into my screen

17:32 last time rlwrap consumed it for 10 hours

17:33 but I wonder how can we hack the repl to run stuff form inside

17:33 automatically

17:33 arohner: is there any other way to start a repl? aside from swank or something?

17:34 arohner: (clojure.main/repl)

17:34 you can even

17:34 (binding [*print-length* 42] (clojure.main/repl))

17:35 that probably won't work if you're connecting over swank

17:36 alexyk: arohner: so I'd put it into a file, myrepl.clj? what's the full command line then?

17:37 java ...clojure on classpath... clojure.main myrepl.clj # ?

17:37 arohner: alexyk: yup

17:37 alexyk: so if not given a file, clojure.main starts repl itself?

17:37 arohner: alexyk: (doc clojure.main/main)

17:38 alexyk: ,(doc clojure.main/main)

17:38 clojurebot: "([& args]); Usage: java -cp clojure.jar clojure.main [init-opt*] [main-opt] [arg*] With no options or args, runs an interactive Read-Eval-Print Loop init options: -i, --init path Load a file or resource -e, --eval string Evaluate expressions in string; print non-nil values main options: -r, --repl Run a repl path Run a script from from a file or resource - Run a script from standard input -h, -?, --help Print this help me

17:38 alexyk: aha

17:38 arohner: alexyk: it's longer than clojurebot will print, and looks better formatted correctly ;-)

17:38 alexyk: arohner: somehow I feel more energized to read it along with 222 other people :)

17:38 and clojurebot

17:39 damn, 4 escaped

17:39 arohner: oh, another option would be to eval (require 'myuser.clj)

17:40 it looks like eval'ing gets run inside the repl

17:41 alexyk: arohner: that's good, no need to modify launchers

17:41 stick stuff into user.clj and user-eval.clj

17:42 arohner: you're not using the --init option, are you?

17:42 I think that does (require 'foo) for you

17:42 alexyk: arohner: how does it know to bind before, but eval after, repl-in'? no --init, never heard of it

17:42 arohner: clojure.main --init foo file.clj

17:42 alexyk: but I can

17:42 init is ok

17:43 arohner: if you specify a file and no --repl, it runs the file and quits

17:45 man, it seems like slime-repl has an n^2 loop somewhere

17:45 finding parenthesis or something, but it gets sluggish after awhile

17:47 technomancy: arohner: there's a clear-output command

17:47 but I haven't noticed it myself

17:48 arohner: technomancy: I'm running an old, funky version. maybe it's been fixed already

17:49 hah: Warning (undo): Buffer `*slime-repl clojure*' undo info was 33180469 bytes long.

17:49 The undo info was discarded because it exceeded `undo-outer-limit'.

17:49 there's your problem

17:49 technomancy: thanks

17:58 duncanm: is there an easy way to queue up agents so that i don't have too many concurrent agents running at the same time?

18:00 hiredman: duncanm: send uses a fixed-sized threadpool, so it will only run 2+cores actions

18:01 duncanm: hiredman: what about send-off?

18:01 hiredman: send-off is an open pool, it grows as needed

18:04 duncanm: hiredman: i have a big grid of tiles, and these tiles show up one by one - right now, there's loop that looks out for these tile, and for each tile, it fires off some agents looking for adjacent tiles, and stalls when the adjacent tiles are not available (yet)

18:04 hiredman: so that seems to be a reasonable design; but the issue is, right now i want to run it on a grid where all the tiles are already there - i don't want all the agents to go crazy all at once (is that a problem?)

18:07 hiredman: the looking for tiles part sounds like a canidate for send-off, and the other stuff you do (once the tile is found?) maybe for send

18:09 duncanm: hiredman: http://gist.github.com/296362 - i think you saw this yesterday already

18:09 hiredman: the looking and calculating stuff is all in one step

18:10 hiredman: *shrug*

18:10 duncanm: also, i feel kinda guilty using a map with [x y z] keys instead of something more specific

18:11 in fact, a sorted-map

18:12 hiredman: oh! i can just wrap the 'really-calculate-offset' part in another agent....

18:12 hiredman: you could thread it through a few sends and send-offs to the same agent

18:12 duncanm: (not (false? tile)) (send (agent "calculating...") really-calculate-offset file (:file tile) direction)

18:12 hmm

18:12 ahh

18:12 hiredman: sort of CPS with agents

18:13 duncanm: right

18:13 hiredman: *agent* is bound to the current agent in an executing action

18:14 duncanm: i'm only using send-off because of the Thread/sleep

18:14 checking if the tile exists doesn't involve IO, because i have an in-memory set for all the known files

18:14 a ref to a set

18:15 hiredman: i fear that i'm over-engineering - the problem itself doesn't actually have much concurrency to it

18:17 hiredman: you could use future and hydra :D

18:17 duncanm: what's hydra?

18:17 i should look into using future

18:17 AWizzArd: ,(find-doc "hydra")

18:17 clojurebot: nil

18:18 hiredman: ~hydra

18:18 clojurebot: It's greek to me.

18:18 hiredman: clojurebot: worthless

18:18 clojurebot: Gabh mo leithscéal?

18:19 hiredman: http://github.com/hiredman/Repl/blob/master/src/hiredman/hydra.clj

18:19 duncanm: hmm, what's the difference between future and agent?

18:20 hiredman: a future is one shot, you cannot send an action to it

18:20 duncanm: and futures are run off a finite threadpool?

18:20 hiredman: hydra is a linkedblocking queue that when deref'ed gives you a lazy seq of the items placed in the queue

18:21 basically it is a sort of shared message bus

18:21 duncanm: futures use the same threadpool as send-off

18:21 (so yes)

18:21 duncanm: so it's not finite, right? it grows as needed?

18:21 hiredman: uh

18:22 what is the difference?

18:22 duncanm: 18:00 <hiredman> duncanm: send uses a fixed-sized threadpool, so it will only run 2+cores actions

18:22 either way

18:22 hiredman: Repl uses hydra and ends up with 23 threads blocking waiting for stuff at startup

18:23 duncanm: i should probably try it and see if it thrashes my machine before thinking about all this

18:23 hiredman: duncanm: the send threadpool is bounded, the send-off is not

18:23 duncanm: and you're saying future's threadpool is not bounded?

18:24 hiredman: "the send threadpool is bounded, the send-off is not" + "futures use the same threadpool as send-off" = "future's threadpool is not bounded"

18:24 duncanm: hiredman: agreed

20:02 kmurph79: is anyone using textmate? the clojure bundle doesn't autoformat correctly

20:19 avarus: hi kmurph79

20:19 which bundle are you using?

20:19 I know two, but I don't like both

20:19 for me the parens highlighting doesn't work

20:19 sucks incredibly

20:19 kmurph79: avarus: nullstyle's

20:20 i guess we should go to emacs?

20:20 avarus: http://github.com/stephenroller/clojure-tmbundle <-- at least this works

20:20 ya, I guess :(

20:21 I tried aquamacs...seems easy but is a pita as well if you want to do more :P

20:21 kmurph79: the bundle code is pretty scary, not sure how to fix it

20:21 avarus: hehe

20:22 and it's old, not updated since 2 years or so

20:22 kmurph79: i've used carbon emacs with success previously

20:23 textmate is just so much easier

20:23 avarus: there is a lisp bundle on the svn server at macro* but I haven't tried it yet

20:23 looks old, probably sucks as well .P

20:24 tomoj: avarus: it's a pita because emacs is difficult to learn?

20:25 avarus: because I never used emacs before

20:25 I don't know if it's hard to learn

20:25 never tried to

20:25 tomoj: ah

20:25 it is, I think :)

20:25 jasapp: it's not hard to learn the basics

20:25 tomoj: if I say "it's worth it" I guess it won't mean much because I'm just another emacs zombie

20:26 sure, type a key to have that character show up on the screen?

20:26 jasapp: yeah, I'm just an emacs zombie too

20:26 tomoj: arrow keys and mouse work too, so

20:26 jasapp: avarus: do you use screen?

20:26 avarus: on my server I do, not on my workstation

20:26 tomoj: I never used textmate for clojure so I dunno what features feel missing for an emacs noob

20:27 jasapp: think of emacs as a version of screen that's actually a text editor

20:27 avarus: tomoj: imagine clojure or lisp code without parens being highlighted

20:28 not being matched

20:28 tomoj: hard for me to imagine clojure or lisp code without parens

20:28 avarus: just horror

20:28 tomoj: oh, I see what you mean

20:28 but, what feels missing in emacs I mean?

20:28 i.e. what makes you want to use textmate instead

20:29 kmurph79: textmate beats emacs for 90% of my actions, but emacs has a bunch of crazy stuff

20:29 tomoj: I guess general editor stuff feels easier

20:29 hmm

20:29 jasapp: can you evaluate clojure code with a command in textmate?

20:29 avarus: eh yes, I want to use textmate because it's idiot-proof

20:29 tomoj: I highly doubt textmate could beat emacs for 90% of your actions if your actions include typing clojure code

20:29 kmurph79: tomoj: probably not

20:29 tomoj: looks like they have a hacked up repl

20:29 jasapp: ahh

20:29 tomoj: runs in screen in the background

20:30 avarus: that would not even be a requirement for me :)

20:30 just proper highlighting would be enough :>

20:30 tomoj: it should be, imo

20:30 avarus: na, i have my scripts

20:30 tomoj: you have scripts which amount to a repl in-editor?

20:30 avarus: and when I want the repl, I can start it :)

20:31 tomoj: eh, maybe someday you'll understand :P

20:31 or like I said maybe I am just a zombie

20:31 avarus: what do you mean?

20:31 tomoj: I mean I could not imagine using textmate for clojure even if it had highlighting

20:31 (and parens matching)

20:32 * technomancy mumbles braaaaaaaaaaains

20:32 avarus: I have no special requirements for things like that :)

20:33 blbrown_win: ,(+ 1 1)

20:33 clojurebot: 2

20:34 tomoj: huh, waitaminute

20:34 blbrown_win: ,(.replaceAll " x " "x" "y")

20:34 clojurebot: " y "

20:34 tomoj: M-. just opened up core.clj for me

20:34 blbrown_win: ,(.replaceAll " x " "\\w+" "y")

20:34 clojurebot: " y "

20:34 blbrown_win: ,(.replaceAll " x " "\\w+" "y")

20:34 clojurebot: " y "

20:34 blbrown_win: ,(.replaceAll " x " "\\w" "y")

20:34 clojurebot: " y "

20:34 blbrown_win: ,(.replaceAll " x " "\w" "y")

20:34 clojurebot: Unsupported escape character: \w

20:35 jasapp: I love M-.

20:35 tomoj: guess it only works for clojure.jar?

20:35 blbrown_win: ,(.replaceAll " x " "\\s" "y")

20:35 clojurebot: "yxy"

20:35 tomoj: I thought it didn't work for jars at all

20:36 jasapp: I found out about it a month or two ago, and it's opened jars since then.

20:36 I think

20:36 tomoj: huh, appears to work for any clojure jars, yeah

20:36 someone told me the other day it only worked for .cljs on the classpath

20:37 anyway, that's a good example I think. point at a function and press M-. and you jump to the function's definition

20:37 cmd-t in textmate is pretty cool, but

20:40 * tomoj stops proselytizing

21:11 avarus: good night

21:11 *megayawn

21:52 AWizzArd: ~max people

21:52 clojurebot: max people is 245

22:12 BrandonW: is anyone here familiar with the partial function vs currying?

22:13 i feel that i might have an obsession with understanding this... haha

22:14 hiredman: ,((partial (partial + 1) 2) 3)

22:14 clojurebot: 6

22:15 BrandonW: right, in Programming Clojure, it defines a faux-curry as (apply partial partial args)

22:16 hiredman: I doubt it

22:16 BrandonW: (defn faux-curry [& args] (apply partial partial args))

22:16 hiredman: what page?

22:16 BrandonW: 145

22:16 on the text version

22:17 at the bottom

22:17 Lazier than lazy, soon after the gray box titled 'Faces of def'

22:18 hiredman: that is dumb

22:18 BrandonW: i see that the partial function is extremely close to faux-curry, but i don't understand what the significance of faux-curry is, if you have to add an extra set of parens to force it to eval

22:18 hiredman: BrandonW: you don't

22:19 BrandonW: is there a better implementation of curry out there that doesn't require the extra eval?

22:19 hiredman: ,(letfn [(faux-curry [& args] (apply partial partial args))] (faux-curry +))

22:19 clojurebot: #<core$partial__5034$fn__5036 clojure.core$partial__5034$fn__5036@16c426b>

22:19 hiredman: BrandonW: you can't really curry in clojure because functions can (and often do) have variable arity

22:20 ,(letfn [(faux-curry [& args] (apply partial partial args))] ((faux-curry +) 1))

22:20 clojurebot: #<core$partial__5034$fn__5036 clojure.core$partial__5034$fn__5036@83dcf8>

22:20 hiredman: ,(letfn [(faux-curry [& args] (apply partial partial args))] (((faux-curry +) 1) 2))

22:20 clojurebot: 3

22:21 hiredman: that is not really currying because + can a variable number of args, so there is no way to tell when you finished applying

22:21 BrandonW: right

22:21 so if it was real currying, would it work exactly the same way as partial already does?

22:21 except that once it knew all args were satisfied, it would evaluate the result?

22:21 hiredman: yes

22:22 BrandonW: i don't understand what the point of faux-curry is then

22:22 it seems to complexify the partial method for a reason i don't understand

22:22 err partial function :D

22:23 hiredman: BrandonW: partial takes a function and at least one argument

22:23 you can't partially apply a function to nothing

22:24 partial results in a function that has been partial applied, faux-curry will result in a function that can be partially applied to one argument

22:24 but yes, I think faux-curry is dumb

22:25 ,(pl (↕map (replicate 3 (range 3)) call · (⌽map inc)))

22:25 clojurebot: ((1 2 3) (1 2 3) (1 2 3))

22:25 danlarkin: clojurebot dsl scares me

22:25 johannh: Is there a map-accum (like Haskell's) anywhere in clojure-contrib? I can't seem to find it.

22:26 hiredman: johannh: what does map-accum do?

22:26 johannh: It threads state through a map. Like scan, if that helps. Half-map, half reduce.

22:27 hiredman: example input and output?

22:31 johannh: (map-accum (fn [acc x] [(assoc acc x) (acc x)]) #{} '(:a :b :b :c :d :c)) -> (nil nil :b nil nil :c)

22:31 It takes a function that takes a state and and value, and returns a new-state and a new-value.

22:32 Given an initial-state and a list, it threads that state through the items in the list, collecting the values as it goes.

22:32 hiredman: #{} is a set

22:32 assoc won't work

22:32 johannh: Shoots. conj. I keep forgetting. Is that right?

22:33 hiredman: how is that different from a reduce?

22:33 conj will work sure,

22:33 or a fold?

22:34 johannh: Oh, sorry. The result should be [final-accum new-list], so [#{:a :b :c :d} (nil nil :b nil nil :c)]

22:34 Well, it's a reduce on the accumulating parameter, but like a map on the input.

22:35 Reduce/fold takes a seq and returns a single item. Map takes a seq and returns another seq.

22:35 In any case, sounds like I might as well implement my own.

22:35 hiredman: hmm

22:39 johannh: Another example: (map-accum (fn [sum x] [(+ sum x) (* x sum)]) 0 '(1 2 3)) -> [6 '(0 2 9)]

22:39 hiredman: ,(reduce (fn [{:keys [accum result]} x] {:accum (conj accum x) :result (accum x result (conj result x))}) {:accum #{} :result []} [:a :b :b :c :d :c])

22:39 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: PersistentHashSet

22:39 hiredman: gah

22:39 teaches me to be clever

22:40 ,(reduce (fn [{:keys [accum result]} x] {:accum (conj accum x) :result (conj result (accum x))}) {:accum #{} :result []} [:a :b :b :c :d :c])

22:40 clojurebot: {:accum #{:a :c :b :d}, :result [nil nil :b nil nil :c]}

22:42 hiredman: ,((comp (juxt :accum :result) reduce) (fn [{:keys [accum result]} x] {:accum (conj accum x) :result (conj result (accum x))}) {:accum #{} :result []} [:a :b :b :c :d :c])

22:42 clojurebot: [#{:a :c :b :d} [nil nil :b nil nil :c]]

22:43 johannh: The context is that I'm trying to unmarshall a vector of values. As I go, I want to thread a map of id->refs through, so if I run into a reference to a ref that I've seen before, I can insert the same reference.

22:44 hiredman: why not reduce into a map of ids to refs?

22:46 johannh: Because I want to return the vector of unmarshalled-refs, not just the ref lookup map.

22:46 I think that's the first time I actually saw a use of juxt.

22:47 hiredman: well, it's new

22:55 johannh: That's a nice example, thanks. How does the (fn [{:keys [accum result]} x ..) work. I feel like I've seen that before, but it's not syntax I'm familiar with.

22:56 Ah, found it in the destructuring docs. I should remember that.

22:58 wilig: newbie question: why is this false? (contains? [:user :password :email] :user)

22:58 hiredman: ,(doc contains?)

22:58 clojurebot: "([coll key]); Returns true if key is present in the given collection, otherwise returns false. Note that for numerically indexed collections like vectors and Java arrays, this tests if the numeric key is within the range of indexes. 'contains?' operates constant or logarithmic time; it will not perform a linear search for a value. See also 'some'."

22:58 hiredman: good?

22:59 wilig: ah, ok.

23:03 somnium: johannh: theres the state monad in c.c.monads, which sounds exactly like the haskell fn you describe

23:03 though a reduce or loop is more common in clojure

23:06 johannh: I don't think the state monad is quite it. Monads go from M a -> (a -> M b) -> M b, so if the monad were just keeping around state, you'd have to provide some extra rule to accumulate the state.

23:08 Maybe I don't understand the state monad well, but I figured it would be going from [state x] -> (x -> [state' y]) -> [state'' y'], where the monady-bit would be responsible for combining state and state' into the final result.

23:09 Here, my basic function is state -> x -> [state' y], which is different.

23:10 somnium: thats the basic signature of it as Ive read (I cant really claim to understand them)

23:14 yes, so in m-bind (?) you decide what to do with y, so you can use an accumulator between do forms (sorry if my vocabulary is imprecise, I barely know haskell or monads)

23:15 in any case in c.c.monads theres an example with an accumulator iirc

23:16 johannh: Eh, I don't know them well myself, but I just re-read the ever-useful Typeclassopedia a few days ago, while wrestling with this same problem. It just feels like there should be a monad answer, but I couldn't find it.

23:18 I went through a short Haskell kick about this time last year, while in a haze of baby-related sleep deprivation. Memory's fuzzy.

23:21 somnium: ah then reduce or loop will probably be much easier since theres not so much 'stateful' behavior

23:24 ,(require clojure.contrib.monads)

23:24 clojurebot: java.lang.ClassNotFoundException: clojure.contrib.monads

23:25 somnium: ,(use 'clojure.contrib.monads)

23:25 clojurebot: java.lang.IllegalStateException: write already refers to: #'clojure.contrib.pprint/write in namespace: sandbox

23:27 somnium: ,(require '[clojure.contrib.monads :as m])

23:27 clojurebot: nil

23:27 somnium: ,(doc m/state-m)

23:27 clojurebot: "; Monad describing stateful computations. The monadic values have the structure (fn [old-state] [result new-state])."

23:28 somnium: johannh: is that the signature or am I misunderstanding (quite probable)

23:33 johannh: Hm. It's not quite it. Really, I have (fn [input old-state] [result new-state]); the result depends on a input, not just the state.

23:36 somnium: ah, I see

23:36 johannh: Ah, okay. I get it. The state monad would work.

23:37 It would just have to be (fn [input] (fn [old-state] [result new-state])); it's a partial-application.

23:37 somnium: probably I would use loop here to be honest :) I just happened to find the state-monad useful in practice last week

23:38 ,(doc m/state-t)

23:38 clojurebot: "([m]); Monad transformer that transforms a monad m into a monad of stateful computations that have the base monad type as their result."

23:39 somnium: this thing too, but Ive drawn the line at transformers thus far :)

23:40 hth

23:41 johannh: Well, for now map-accum will solve my problem, so I think I'll stick with that, but if things get hairier, I can look deeper into the state monad.

23:41 I don't know if that helped, but it was fun, so thanks.

23:44 somnium: :)

Logging service provided by n01se.net