#clojure log - Dec 14 2010

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

1:10 amalloy: is there a convenient way to tell whether (:foo some-map) returned nil because :foo is present with a value of nil or not present?

1:11 cky: amalloy: Of course there is! Just don't allow the map to contain nil, and you're all set. :-P

1:11 amalloy: (Cue strategy used by Java's concurrent collections.)

1:12 amalloy: cky: psh. so you'd think, but then it turns out you have to cater to users who will have your code to sneak a nil in :)

1:12 *hack

1:13 cky: Yipes!

1:16 technomancy: amalloy: (:foo some-map ::not-found)

1:16 amalloy: technomancy: yeah, i guess

1:16 i was hoping for a choir of angels, i guess, or something equally magic

1:17 technomancy: CL does it with multiple return values, but that seems like an annoying special-case to have to support

1:20 amalloy: technomancy: yeah. multiple return values seem useful on the surface, but i'm pretty happy with having simple&powerful destructuring-bind instead

1:21 cky: Both have uses.

1:21 Sometimes, you do need to distinguish between a list return and an MV return. :-)

1:22 * cky uses MV in Scheme more than the average non-Scheme programmer. :-P

1:24 amalloy: cky: you never have to distinguish. in the cases where you might want either one, just always return a list; [[1 2]] vs [1 2] is a fine distinguisher

1:25 cky: But that requires a special protocol: "always return a list/vector".

1:25 joshua__: amalloy: you could create a choir-of-angels predicate function and have that predicate return true if it turns out the item [:symbol nil].

1:25 Than do something like (some choir-of-angels your-map) ;p?

1:26 cky: I'm thinking of a generalised comp(ose) function. If you have a binary function somewhere in the chain, some way for the previous function to return two values would be nice.

1:26 Without requiring all the functions in the chain to return a list, that is.

1:26 amalloy: cky: that's true, i guess

1:27 i haven't lived in that environment long enough to see how often it's useful, but i can imagine it would be

1:27 cky: *nods* I've certainly come to discover that CL, Scheme, and Clojure programmers all think in very, very different ways, according to what their respective language affords.

1:28 amalloy: cky: i've tasted all three, but only stuck around for the second sip of clojure

1:28 cky: I certainly cannot claim to know how CL or Clojure programmers think. :-)

1:28 amalloy: it's more of a judgment on me than the languages, i think

1:28 cky: *nods*

1:28 And I'm sure there are many Clojure idioms that I have yet to appreciate, for sure.

1:29 amalloy: since i tried scheme...eight years ago, and CL during a depressive phase

1:29 cky: Hahahahaha.

1:30 amalloy: cky: the elegant clojure trick that still blows my mind is http://rosettacode.org/wiki/Fibonacci_sequence#Clojure

1:30 joshua__: cyk: Watching the videos of the things clojure has to offer is sort of odd for me. I'm like, "wow this stuff is all so neat I wonder when I'll use some of it."

1:32 cky: $source iterate

1:32 sexpbot: iterate is http://is.gd/iImcN

1:33 cky: amalloy: That's pretty neat. I'm going to see what iterate is all about. :-P

1:33 amalloy: joshua__: most IRC clients have a tab-completion feature for nicks, so that you don't have to spell out the name (i mention this because you got cky wrong, no offense intended)

1:33 cky: Hahaha, Clojure implements what's known as "odd streams".

1:34 I hear (but am not knowledgeable enough about streams to say anything authoritative) that odd streams are problematic, and that even streams don't have those problems.

1:35 The automatic use of lazy-seq for things like map, etc. is pretty neat, though.

1:36 joshua__: amalloy: Thank you so much, that is such a nice feature.

1:36 amalloy: cky: i don't know anything about stream modulo, i'm afraid

1:38 cky: The Rationale section of http://srfi.schemers.org/srfi-41/srfi-41.html describes the two concepts, but their ramifications go way over my head.

1:38 amalloy: joshua__: use enough unix tools regularly, and you find yourself hitting tab whenever you don't feel like typing, just in case it works

1:38 cky: yeah, the lazy-seqs everywhere make TCO a much less pressing feature

1:38 mabes_: Rich's thoughts on it from 2008: http://groups.google.com/group/clojure/browse_thread/thread/d94f9434155703fd?pli=1

1:39 cky: mabes_: Thanks for the link.

1:39 hiredman: thats outdated

1:40 mabes_: figured

1:40 hiredman: clojure seqs are full lazy, baring chunking

1:40 amalloy: cky: it looks like you can make clojure seqs even or odd, and odd is the default in things like map

1:40 technomancy: interesting that the laziness semantics changed twice about a year apart

1:42 cky: *nods*

1:42 amalloy: er, even is the default, rather. because they look like (delay (cons 1 (delay (cons 2 (delay ())))))

1:43 you happened to look at iterate, which puts x first in a non-lazy way, because x is already known

1:45 cky: Ah, okay.

1:54 notsonerdysunny: Can I have protocols dispatch on the types of the arguments ..?

1:54 or does it necessarily have to be only the arity?

1:56 raek: only dispatch on the first type (one per arity)

1:57 i.e. the way java methods work

1:59 notsonerdysunny: raek .. I am not familiar with java .. but what exactly I want is .. let us say I have complex data type which defines the function * .. I would like * to work different depending on whether both arguments are complex or if one of them is a real number .. how can I achieve this?

1:59 raek: sounds like a use case for multimethods

1:59 notsonerdysunny: I come from C++ is it similar to c++

2:00 raek: yes

2:00 the restrictions of what protocols dispatch on, that is

2:01 notsonerdysunny: in c++ I can do this using method overloading .. I can have (* complex complex) (* complex int) can this be done with protocols?

2:03 raek: hrm, I don't think so (someone, please correct me if I'm wrong)

2:03 if my assumption is correct, protocol methods are only Objects to Object

2:05 notsonerdysunny: you might be interrested in this: http://clojuredocs.org/clojure_contrib/clojure.contrib.generic.arithmetic

2:06 there you could define a method for [::complex ::complex]

2:08 dnolen: raek: notsonerdysunny: something like can be done with definterface and type hints.

2:08 https://gist.github.com/740099

2:09 notsonerdysunny: what do I gain from using protocols over definterface?

2:09 to me they almost seem interchangable

2:09 dnolen: notsonerdysunny: definterface is low level, not fns.

2:10 note that I call mehthods not fns.

2:10 zmyrgel: If I have (:use (foo bar)) in my baz file's ns macro, shouldn't the baz be able to resolve class name of record defined in foo/bar.clj?

2:11 opqdonut: no, you need to import that class separately

2:11 and, get this, import it after the use

2:11 raek: the definterface way has one restriction that the multimethod way has not: you have to enumerate all type combinations. it is not possible to add one case later.

2:11 opqdonut: or just use the fully qualified name foo.bar.Record

2:15 zmyrgel: hopefully clojure namespace handling gets simpler in the future...

2:17 raek: another common solution (which has other benefits as well) is to expose a constructor function to the lib users, rather than making them calling the record constructor themselves

2:18 replaca: anyone hanging out here you uses both paredit and tmux?

2:18 zmyrgel: I use constructor function with my other class

2:26 notsonerdysunny: thanks dnolen .. I think your gist helps ..

2:26 Thanks raek ..

2:27 would you expect interfaces to be more efficient when compared to protocols..

2:28 dnolen: notsonerdysunny: I would still do it with protocols and use instance?

2:29 notsonerdysunny: https://gist.github.com/740099

2:29 definterface 1 second vs. protocols 13ms for 1e6 iterations

2:29 because of reflection

2:30 sleep time for me, hope that helps.

2:31 notsonerdysunny: thanks dnole

2:31 good night

2:31 thanks dnolen

2:36 amalloy_afk: notsonerdysunny: i wouldn't put a lot of weight behind dnolen's benchmark - it looks like he threw it together in a hurry, and it's not comparing anything meaningful

2:37 or maybe i'm just having trouble reading it

2:40 amalloy: eg the JIT won't be warmed up while definterface is running, but i think most of my other objections were misunderstandings. sorry dnolen!

2:41 LauJensen: amalloy: There a blogpost on benchmarking on Best In Class :)

2:41 amalloy: LauJensen: augh, will i never escape from my one careless remark!? :)

2:42 LauJensen: No! But, I have noticed that you're giving superior advice these past days :)

2:42 amalloy: LauJensen: i haven't read BIC for a couple weeks...maybe that's it

2:43 LauJensen: Aah. I see you make me regret paying a compliment. I wont repeat the mistake

2:44 (read that in a repressed angry japanese accent)

2:44 amalloy: *chuckle*

2:50 notsonerdysunny: https://gist.github.com/740122

2:50 It is unable to resolve the record name complex when I compile the tt1.clj file .. can anybody tell me as to where I am making a mistake?

2:52 tomoj: "foo." is a mark of java

2:52 you need to import the class, not require

2:53 notsonerdysunny: ah thanks ..!

2:53 tomoj: in the case where you want both the constructor and the methods you have to both import and require

2:53 notsonerdysunny: oh ic

2:54 tomoj: better to just define a factory fn and require it all?

2:54 notsonerdysunny: I don't quiet get what you said last..

2:58 tomoj: I mean, often you end up needing a factory fn anyway, some fn in the namespace that calls the constructor but is more convenient

2:58 if so, you don't need to import the constructor because you can require the factory fn along with the methods

2:59 notsonerdysunny: ah ic .. thanks tomoj

3:06 tomoj .. can you tell me as to how interface differs from protocols .. Is there a difference btw methods and functions?

3:07 tomoj: difference between interface methods and protocol functions?

3:07 raek: methods are not function objects, so you cannot pass them around as arguments to function, store them in variables, etc

3:07 protocol methods are clojure functions too

3:08 so defprotocol will def a number of functions on the current namespace

3:09 notsonerdysunny: yes tomoj .. that is what I meant to ask .. but I think raek's responses clear things up...

3:10 raek: also, when you call a java method without knowing which one of the overloaded variants that applies, clojure will generate code for looking up that at runtime

3:12 when a call is made, it needs to iterate over the possible variants of the method in the interface and select the one that matches the types of the objects that you passed in that case

3:12 notsonerdysunny: so bottom line is if one does not care about storing the functions and passing them around as arguments to other higher-order-fns then definterface gives a better flexibility in terms of dispatch

3:13 raek: well, multimethods are always more flexible

3:14 also, you need to create some "dummy object" that the method is invoked on, if you use the definterface aproach to your problem

3:14 (.plus dumme-object float-argument complex-argument)

3:15 and because of the reflection invloved, you won't get the performance that you usually expect with non-reflective method calls and protocol calls

3:16 but, yes. definterface allows you to overload on type.

3:16 notsonerdysunny: so would definterface give me better performance than multimethods in this kind of dispatch?

3:17 raek: that's a good question... :)

3:17 * raek thinks about how this could be easured

3:17 raek: *measured

3:19 notsonerdysunny: Thanks raek ..

3:20 It looks like finally things are falling in place

3:21 tomoj: if your choice between definterface and multimethods is about performance, mustn't you be pretty far along?

3:24 notsonerdysunny: It looks like I have to just use multimethods and stop worrying about performance .. until I am done ..:)

3:24 raek: (my feeling is that multimethods should have similar or better performance compared to reflective method calls. however, it would be nice if I could justify that feeling experimentally... :-) )

3:27 amalloy: notsonerdysunny: i have the same feeling raek does. multimethods must be faster than plain reflection

3:36 raek: ...and the results! https://gist.github.com/740151

3:37 (criticism of the test is welcomed)

3:38 notsonerdysunny: no matter whether flexibility, elegance or performance is concerned, it seems that multimethods is the winner for this problem

3:56 amalloy: raek: can't you avoid the reflection warnings in the interface version by type-hinting dummy?

3:57 (add a comma before dummy if you prefer disrespectful suggestions(

3:58 raek: :)

3:59 in the general case, the compiler would still not know the types of the two arguments at compile time (which was the point in this case)

3:59 hinting with ^MixedAdditionImpl didn't change anything in my benchmark

4:00 amalloy: fair enough

4:01 raek: of course, hinting all the args gets the reflection away, ("Elapsed time: 57.745888 msecs"), but then one could as well have written two separate functions (since one knows the type in advance)

4:01 amalloy: raek: sure

4:02 i just wanted to make sure there was no incidental complexity

4:03 raek: I appreciate the skepticism. :)

4:03 or criticism...

4:15 amalloy: raek: speaking of criticism, http://is.gd/iIGFt seems to think i was unkind in http://is.gd/iIGOg - is he overreacting, or was i undiplomatic?

4:18 ejackson: Good Morning

4:59 kotarak: amalloy: He's certainly speaking about the second message. Which could be considered "undiplomatic" by a very small degree. All-in-all I think he's overreacting.

6:52 nunb: anyone using moustache for writing webapp routes?

6:52 experiences/kudos/gripes?

6:54 bsteuber: nunb: didn't use it a lot yet, but it works out nicely so far

6:56 kotarak: nunb: use it several times in smaaaall projects. Worked quite well so far.

7:21 raek: nunb: complete documentation. *everything* can be read from the grammer. I like it very much.

7:22 my personal experience is that I tend to write complete handlers (modulo the stuff that I factor out into middleware) outside the routes, and only use moustache to select the right handler

7:46 * GOSUB is giving a talk about Clojure's solution to the Expression Problem this Saturday in Pune, India.

7:46 GOSUB: nunb

7:51 fogus`: GOSUB: Good luck. That is a tough talk to give. :-)

7:51 GOSUB: fogus`: hehe, thanks. but I stand on the shoulders of giants :)

7:52 fogus`: GOSUB: Well, I'm sure you will be fine. It's the audience that is the tough part.

7:56 GOSUB: fogus`: I agree. This is going to be mostly Java people.

7:56 fogus`: I thought instead of doing a intro talk, it's better to talk about a problem they might understand.

7:57 fogus`: btw, is there a problem with the video of your talk on blip.tv? seems to be just about 18 mins in duration.

7:57 fogus`: No idea. I haven't watched it.

7:57 GOSUB: ok

7:57 cemerick: GOSUB: knock 'em dead :-)

7:58 GOSUB: cemerick: haha, don't want to kill those poor masochists :)

7:59 Java programmers remind me of Silas.

7:59 cemerick: GOSUB: hrm; ok, knock 'em into a delirious wonder, from which they'll emerge transformed.

7:59 GOSUB: cemerick: that, indeed, is the intention :)

8:00 will Clojure 1.3.0 be released within the next couple of weeks?

8:00 cemerick: almost assuredly not

8:01 GOSUB: cemerick: ah, these are just the alphas. the betas and RCs are yet to come.

8:01 cemerick: yeah, we've a ways to go. I'm hoping it gets tied up before, say, May

8:02 GOSUB: cemerick: hmm. are we expecting a lot of breaking changes from now? what features are in the pipeline?

8:02 basically I was wondering if we could start using 1.3.0-alpha-x for a new project.

8:03 cemerick: As far as features, anything @ http://dev.clojure.org/display/design/Home is presumably on the table, at the very least.

8:03 GOSUB: ok

8:03 cemerick: I was in production with 1.2.0 SNAPSHOTS before 1.1.0 was released, so… ;-)

8:04 GOSUB: wooh, async IO!

8:05 cemerick: you have titanium balls!

8:06 cemerick: lol

8:06 GOSUB: you, sir, have a way with compliments!

8:06 GOSUB: cemerick: please don't mention it :)

8:28 fogus`: Sigh. The "Implementing multimethods in pure Clojure" thread had great potential.

8:30 GOSUB: cemerick: is there any way to tell jetty to reload a war once it has been modified (replaced by a new one)

8:33 cemerick: GOSUB: I believe there's a autodeploy option that will watch for new/updated war files in the designated directory.

8:34 GOSUB: cemerick: ok. checking.

8:35 cemerick: there seems to be some Maven plugin to do this.

8:36 cemerick: how would you recommend doing deployments without restarting the app?

8:36 cemerick: jetty-maven-plugin, sure, but that's at dev time -- I thought you were talking about in production

8:36 GOSUB: cemerick: yes, we need this feature for production.

8:36 cemerick: GOSUB: reloading a war implies restarting the app, though not necessarily restarting the container

8:37 GOSUB: cemerick: yes, we would want to restart the app, without restarting the container.

8:38 karmazilla: the way one usually does it involves having more than one server

8:38 GOSUB: karmazilla: fiddling with the load balancer config?

8:38 karmazilla: yes

8:39 GOSUB: karmazilla: that's one way for sure. but I am looking at some other ways.

8:40 cemerick: GOSUB: I agree with karmazilla. There are ways to do hot-deploy, but they vary from container to container. Check out the maven cargo plugin, which attempts to provide a common API and goals for such things.

8:40 GOSUB: cemerick: OK. is that plugin fine for production?

8:41 cemerick: GOSUB: I've only fiddled with it before. Restarting the container has always suited my needs.

8:41 GOSUB: cemerick: OK.

9:15 bobo_: anyone got a tip for a small example task to show protocols or OO in general in clojure? something that you can write in 20mins or so

9:19 dnolen: bobo_: http://clojure.org/runtime_polymorphism, http://clojure.org/multimethods are good places to start first.

9:19 bobo_: im trying to come up with some small tasks for the user group meeting tonight

9:20 chouser: bobo_: Implementing a Clojure print fn can be instructive, if a bit navel-gazing

9:21 dnolen: bobo_: personally I don't reach for protocols unless I'm pretty certain about the domain or performance is really a concern up front (I'll be generating millions instances even in small programs).

9:21 bobo_: print sounds like a good idea, printing time maybe. to be able to take long and date or whatever

9:21 dnolen: bobo_: also I think multimethods are considerable easier to explain than protocols and defrecord/type anyhoo.

9:22 bobo_: yes i agree, i like multimethods

9:22 chouser: oh, but that's polymorphism in particular. Just printing won't touch other OO concepts much.

9:22 gtrak: encapsulation?

9:22 what else is there?

9:23 encapsulation is just a function calling other functions :-)

9:23 bobo_: i liked the talk about the expresion problem, cant remember who gave it but anyway, should say something about that

9:24 chouser: bobo_: you might choose to not call it the expression problem. LtU picked apart that particular term more than the talk itself.

9:24 bobo_: realy?

9:24 and i see now you gave the talk ofc :-)

9:24 GOSUB: bobo_: http://freegeek.in/blog/2010/05/clojure-protocols-datatypes-a-sneak-peek/

9:25 chouser: http://lambda-the-ultimate.org/node/4136

9:25 clojurebot: #<RuntimeException java.lang.RuntimeException: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated>

9:25 GOSUB: chouser: what do you think about Odersky's comment?

9:25 dnolen: chouser: ha, you mean Odersky mostly. I didn't that argument at all. "If it's harder to implement because of my static type system. It's not the same problem"

9:26 GOSUB: dnolen: I think he was trolling.

9:26 dnolen: GOSUB: totally.

9:26 GOSUB: dnolen: especially since he never defended his statement again.

9:27 dnolen: GOSUB: well, I'm sure he's a busy guy with better things to do than read LtU all the time.

9:27 chouser: Mostly it doesn't matter to me. I called it the expression problem because I thought that was what people called it. But regardless of its name, it *is* a problem that many languages have only poor solutions to.

9:27 GOSUB: chouser: let's call it "Strawman Problem" for our purposes.

9:27 or may be "Problem #X"

9:27 cemerick: We could just call our version of the expression problem the Odersky Problem.

9:27 chouser: right

9:27 heh

9:28 GOSUB: cemerick: haha

9:28 clojurebot: #<RuntimeException java.lang.RuntimeException: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated>

9:28 GOSUB: someone please fix clojurebot

9:28 cemerick: I wonder if hiredman is up yet to fix clojurebot

9:30 GOSUB: chouser: are your slides from the strangeloop talk up somewhere? I am talking about the expresion problem on Saturday, may be I could draw some inspiration.

9:31 chouser: GOSUB: http://talk-expression-problem.heroku.com/#1

9:31 dnolen: chouser: btw, any plans for implementing Finger trees with primitive arrays at some point?

9:31 clojurebot: #<RuntimeException java.lang.RuntimeException: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated>

9:31 GOSUB: chouser: great. thanks.

9:32 chouser: dnolen: hm, nope. I'm not sure where I'd use them.

9:32 dnolen: you have an idea?

9:34 bobo_: chouser: i like how thoose slides look, what did you write it in?

9:35 GOSUB: bobo_: showoff.

9:36 bobo_: https://github.com/schacon/showoff

9:36 bobo_: yes found it. thanks

9:37 promising tagline on it

9:37 dnolen: chouser: well I'm curious how well they'd perform for a miniKaren impl. PersitentHashmaps are good, but I really shouldn't need to pay the cost of hashing for what I'm doing.

9:38 chouser: you're using vectors underneath right? Why couldn't you use arrays? (I haven't look at the theory behind FTs. So I could be way off base here)

9:40 chouser: dnolen: no, there are no vectors in the finger tree impl anymore

9:41 dnolen: there were in earlier versions, but it now uses deftypes everywhere

9:43 dnolen: chouser: oh! nice.

9:45 chouser: there's never more than 4 child nodes for any kind of node, so it was reasonable to make 4 different datatypes, each exactly the right size

9:45 (via a macro of course)

9:46 * cemerick was waiting for Tuple4 :-(

9:46 cemerick: ;-)

9:47 chouser: Mine's called Digit4

9:47 cemerick: Generation of it via a macro puts you on the side of the light, though.

9:48 * cemerick is snarky this morning, apparently

9:48 chouser: whew

9:49 cemerick: The world waits with bated breath for my approval, I know.

9:49 * dnolen is really, really ready for a lazy sequences debugger

9:54 dnolen: translating TCO heavy code to lazy sequences is kinda ... tricky.

11:22 jcromartie: would it be good to have a background namespace loader utility?

11:22 like... to be reloading certain namespaces at regular intervals

11:22 or when changed

11:23 ohpauleez: jcromartie: How are you going to identify the namespace has changed?

11:23 chouser: lazytest:watch does that

11:24 ohpauleez: oh yes, yes it does

11:24 jcromartie: interesting

11:24 I guess what I'm *really* asking is: how do I get more interactivity out of my interactive development?

11:25 Without doing (require 'some.stuff :reload) every 5 seconds

11:25 ohpauleez: ahh

11:25 good point

11:25 jcromartie: because I'm running a repl and always having to reload my code and jump into namespaces

11:25 I have an init.clj but (in-ns myproject.core) doesn't seem to work, so I still have to type (in-ns 'myproject.core) every time I start

11:26 if that's what I want to do (and it usually is)

11:26 KirinDave: Man, some truly interesting papers (and programmer-cultural observations) hanging off this article: http://gnuu.org/2010/12/13/too-lazy-to-type/

11:26 jcromartie: I mean, (in-ns 'foo) works fine from init.clj, but it only works in that context... not the repl

11:26 lein loads init.clj and then runs the repl, starting in 'user

11:29 maybe Squeak has me spoiled :)

11:29 I don't know of any REPL language that has that kind of instant reloading though

11:29 KirinDave: jcromartie: Erlang?

11:30 jcromartie: it's not "instant" in that it's two-phase, but I think that's what most people would prefer. Instant reloading could be somewhat surprising as your execution pointers fall into garbage.

11:31 jcromartie: execution what now?

11:33 KirinDave: jcromartie: Well, if you really hot-reloaded everything, your current instruction pointer (or EP, i think it's called in the erlang vm) could point to nonsense. :)

11:33 jcromartie: oh

11:33 I thought you were talking about Clojure

11:34 :)

11:34 that's where I lost you

11:34 KirinDave: No no. I said erlang. :)

11:34 jcromartie: right

11:35 KirinDave: Man, every rubyist I know is mad about that article.

11:35 Adamant: what article?

11:35 KirinDave: the one I posted

11:35 Adamant: the gnuu one, ok

11:35 KirinDave: http://gnuu.org/2010/12/13/too-lazy-to-type/

11:35 Yeah

11:35 I should say "almost every"

11:36 ohpauleez: KirinDave: Thanks for the link, awesome read

11:37 KirinDave: It's funny too, because a lot of ruby metaprogramming is just pining for syntax hacking, which is just pining for lisp macros

11:37 It's sort of a sad day when they're convinced that programming is "dynamic"

11:39 Chousuke: I suspect the dynamic/static split occurs only because we don't yet have a good enough type system :P

11:40 cky: "We" meaning everyone other than Haskell and ML programmers, amirite? :-P

11:41 ohpauleez: haha

11:41 KirinDave: cky: No, even they have problems.

11:41 Chousuke: nah, Haskell has problems too

11:41 cky: :-P

11:42 Chousuke: I suppose ideal would be something that allows you to use arbitrary predicates

11:42 KirinDave: Chousuke: Probably. We've got to get to a point where the type system is an assist. I pine for a better evolution of what CL started

11:42 Chousuke: but I honestly have no idea how that would work in practice. :)

11:43 chouser: yes, arbitrary compile-time assertions

11:43 KirinDave: Chousuke: I mean, we have SOME ideas. :)

11:44 cemerick: Chousuke: Sounds like multimethods. In which case, the application running in production is really just a really long compile cycle. :-P

11:45 KirinDave: cemerick: If type inference is just multi-methods, a lot of people have been wasting their lives.

11:45 Chousuke: but if you could make declarations like "data structures of type Foo have the following properties: ..." and "this function takes a Foo and returns a Foo, that in addition has property X"

11:45 that might be interesting

11:46 cemerick: KirinDave: Insofar as desired behaviour exists that can't really be expressed statically……

11:46 chouser: I'm more interested in "is a pain to express" than "can't be expressed"

11:47 KirinDave: cemerick: Well the whole point of the prior article is that it's actually fairly difficult to find a program that actually uses things which are unexpressable statically

11:47 cemerick: chouser: either/or :-)

11:47 KirinDave: cemerick: Most of what rubyists call dynamic are just macros that the runtime execution pays the price for.

11:48 cemerick: If that's true, then that's a problem for rubyists and their current practice.

11:48 dnolen: KirinDave: what are the rubyists mad about? most the article reiterated the kinds of analysis v8 does to get such good performance out of loosey goosey JS. types don't change much in real programs.

11:48 KirinDave: cemerick: What is difficult to express statically that is dynamic?

11:48 dnolen: They're mad that their assertions are being refuted. That is how the ruby community is, man.

11:49 bsteuber: does anyone know a good hadoop hosting prodiver?

11:49 chouser: the only thing about that article that bothers me is the suggestion that "dynamic" ever meant that all our arguments or containers will regularly have objects of widely varying types.

11:49 KirinDave: cemerick: Sufficient syntax hacking seems to be the solution to many of those woes.

11:49 chouser: Yes.

11:49 chouser: That bothered me as well.

11:50 fogus`: Oh no!!! I ran from Twitter to avoid this conversation... :-(

11:50 KirinDave: fogus`: Trololo.

11:50 fogus`: But it's interesting, man. And it lets us make fun of rabid rubyists (as if excuses or permission were needed).

11:51 fogus`: KirinDave: Oh... well then proceed

11:53 The static guys are in a tizzy about that post too. Sigh.

11:53 technomancy: jcromartie: the repl will start in the :main ns if you provide one

11:53 you can add :skip-aot metadata to the :main symbol in project.clj in the latest from git

11:54 jcromartie: hm

11:56 fogus`: Related: OOP --> POO http://github.com/raganwald/homoiconic/blob/master/2010/12/oop.md

11:58 tgk: Does anybody know if there is an idiomatic way of constraining arguments to functions or the return type of a function? I've tried #^, bit that doesn't seem to have an effect.

11:59 amalloy: tgk: see pre/post conditions

11:59 fogus has an article on those somewhere

11:59 $google clojure post conditions meta map

11:59 sexpbot: First out of 376 results is: Clojure - special_forms

11:59 http://clojure.org/special_forms

11:59 clojurebot: #<RuntimeException java.lang.RuntimeException: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated>

12:00 cemerick: KirinDave: Off the top of my head, Scala's structural typing is an example of an absolutely painful corollary to what is trivial in a dynamic language.

12:01 KirinDave: cemerick: That's not really an answer to the question though.

12:01 cemerick: What scala is trying to do is satisfy its type system. It's not expressing anything different from what a piece of clojure code is expressing.

12:01 tgk: amalloy: writing pre and post conditions for the types don't really seem idiomatic...

12:01 dnolen: speaking of JS, with ArrayBuffers and Object.freeze, JS is looking like a damn fine Clojure target.

12:03 cemerick: KirinDave: For that example, I defer to chouser's difficulty threshold.

12:03 KirinDave: cemerick: But that's not inherent to static typing. :)

12:04 cemerick: That's inherent to scala's specific implementation.

12:04 cemerick: That said, I bet the numbers for structural typing are smaller than they are for multiple dispatch patterns, for example.

12:04 dnolen: tgk: what's not idiomatic about them?

12:05 tgk: dnolen: I guess idiomatic isn't the right word. I would just think (and I seem to remember) that there is some shorthand for restraining types.

12:06 dnolen: tgk: defrecord/type + protocols is another way.

12:07 constrain on the first argument.

12:07 tgk: multimethods yet another way, constrain on all arguments.

12:07 tgk: dnolen: Okay, but multimethods seems like overkill if there is only one implementation

12:08 dnolen: tgk: then use defrecord + protocol. call a protcol fn w/ the wrong type will always throw an error.

12:09 tgk: dnolen: Okay, I guess that's going to be my solution. I'll try it out, thanks.

12:09 jcromartie: so are there any tips or tricks on clojure + slime to make me more productive?

12:09 amalloy: jcromartie: use clojure and slime. each should make you a lot more productive

12:09 jcromartie: yeah :)

12:09 I've been using lein repl

12:10 but now I'm using slime

12:10 amalloy: are you familiar with emacs already, or starting anew there too?

12:10 jcromartie: at first I was like: lein repl

12:10 but now I'm all like: lein swank; M-x slime-connect

12:10 fogus`: tgk: http://blog.fogus.me/2009/12/21/clojures-pre-and-post/ but I suspect you mean something else

12:10 jcromartie: I am familiar with Emacs, but not Slime.

12:11 amalloy: C-c C-k compiles the current input file; C-c M-p sets the repl's ns to the ns of the current file; C-c C-m macroexpands the form at point

12:11 tgk: fogus: yeah, I was hoping for some shorter way of doing it, but thanks :)

12:11 jcromartie: amalloy: wow, those are great

12:12 amalloy: in the repl, M-p and M-n for command history; i'm not sure if that's a "given" in any emacs context

12:12 cemerick: tgk: type hints will constrain the types allowed within an *interop* form, and you can use cast to ensure return types

12:12 The latter is very rarely used.

12:12 amalloy: in source files, M-p and M-n jump to compile errors

12:13 jcromartie: and now I'm all like: C-h m

12:13 :)

12:13 hm

12:14 seems C-c C-k is broken: Wrong number of args (4) passed to: basic$eval635$compile-file-for-emacs

12:14 amalloy: whoa what

12:14 i know nothing about this (technomancy?), but it sounds like a slime/swank/emacs version mismatch somewhere

12:14 jcromartie: maybe something is out of date

12:14 yah

12:15 amalloy: jcromartie: oh, C-c C-e to eval an arbitrary clojure form in the minibuffer if you don't want to go all the way to the repl

12:15 jcromartie: "Versions differ: 20091016 (slime) vs. nil (swank). Continue? (y or n)"

12:16 In my project.clj :dev-dependencies [[leiningen/lein-swank "1.1.0"]]

12:16 amalloy: no swank at all, huh? maybe get a fresh copy of swank-clojure package from elpa?

12:16 jcromartie: I guess that's really out of date

12:17 amalloy: (and of course C-x C-e to eval the clojure form before point, just like regular lisp or .emacs editing)

12:22 jcromartie: what do you all have in project.clj for lein-swank?

12:23 amalloy: jcromartie: i think you want swank-clojure?

12:23 :dev-dependencies [[swank-clojure "1.2.0"] ...]

12:23 jcromartie: buh

12:23 yeah I do

12:23 dnolen: Emacs is also a pretty killer way to work through rhickey's bookshelf. I got SWI-Prolog, Racket, Haskell, SML/NJ REPL all running together.

12:23 jcromartie: I've slapped my project.clj together from various Github REAME files

12:23 ejackson: dnolen: lol

12:23 your brain must be muuuuuush

12:24 dnolen: :D

12:25 jcromartie: wow this is such an improvement

12:25 especially for debugging compilation

12:25 fogus`: dnolen: Been there, done that... still have the scars. :p

12:25 amalloy: jcromartie: i don't know if lein has a "global project", but with cake i can put that dev-dependency in ~/.cake/project.clj and forget about it; it gets magically loaded as a dep in every project

12:25 dnolen: fogus`: really?

12:26 jcromartie: amalloy: is cake a competitor to lein or what

12:26 technomancy: jcromartie: "lein install swank-clojure 1.2.0" will install it across the board

12:27 amalloy: jcromartie: more or less. they're cooperative competitors, in that they're largely drop-in compatible with each other

12:28 jcromartie: ah

12:28 fogus`: dnolen: I once had all manner of things working through Emacs... but I've cleaned up since then

12:29 amalloy: so it's not hard to try out the other one: if you're used to lein and want to try cake, you can more or less just install cake, then replace "lein" in all commands with "cake", or vice versa if you're used to cake

12:30 dnolen: fogus`: what was the problem? Not sure how to work with the the different langs with a reasonable REPL experience otherwise.

12:31 jweiss: anyone had a problem with emacs-starter-kit where if you do slime-connect, it says it connects, but there's no *slime-repl clojure* buffer?

12:31 fogus`: dnolen: No problem. Just rearranged my emacs cfg around and left a lot of stuff out. I add it back in as a find the need for it.

12:32 technomancy: jweiss: it's possible to install slime without slime-repl

12:33 jweiss: technomancy: hm that might have been it

12:33 dnolen: fogus`: yeah I don't do that stuff by hand anymore. I lean on customize-mode.

12:34 jcromartie: does this apply to swank-clojure? http://common-lisp.net/project/slime/doc/html/Examining-frames.html#Examining-frames

12:36 amalloy: jcromartie: not yet, i think

12:37 jweiss: technomancy: what is the autocomplete feature that i'm seeing in C-x C-w? i'm trying to write a new file but it insists on completing the name of an existing file when i hit enter.

12:38 scottj: jcromartie: v works and there there was a way to eval stuff in the top frame I think

12:38 amalloy: jcromartie: http://georgejahad.com/clojure/emacs-cdt.html is crazy awesome for a bit more time investment

12:39 personally i've found the learning curve steep enough to discourage me, since my projects aren't complicated enough to need it

12:42 scottj: jcromartie: re clojure + slime tips/tricks, I made some screencasts at http://youtube.com/emailataskcom

12:43 technomancy: jweiss: that's ido, hit C-f to temporarily disable it

12:48 hugod: jweiss: or C-j to use exactly what you have typed

12:49 jweiss: i see thanks. and how do i customize the starter kit? i tried adding my color settings to .emacs but that results in the starter kit not loading at all

12:50 should i just edit init.el?

12:51 oh i see there's a hint in the readme

13:07 jcromartie: C-c C-c is the BEST THING EVER

13:07 amalloy: jcromartie: oh, i forgot to mention that one :)

13:07 slime is a heady experience, isn't it

13:08 jcromartie: oh, the hyperbolization of our culture... :( why do I give in

13:13 ohpauleez: jcromartie: the power of g :) http://vim.wikia.com/wiki/Power_of_g

13:35 amalloy: jcromartie: the hyperbolization of culture will lead to the death of communication! you are contributing to a world-threatening problem!

13:37 jcromartie: amalloy: it is the BIGGEST PROBLEM EVER

14:17 paredit in the REPL? yes

14:17 thank you Emacs

14:21 the fact that I could type this correctly, the first time, in the REPL, is thanks entirely the paredit: (db/with-conn (def data-cols (into {} (map #(vector % (map first (comp db/text-type? second) (db/columns %))) data-tables))))

14:22 amalloy: jcromartie: plz give teh c0dez. i had trouble setting up paredit in the repl and eventually gave up

14:22 jcromartie: M-x paredit-mode

14:22 that's all I ddi

14:22 did

14:23 amalloy: iirc that caused some problems for me

14:24 scottj: I use (dolist (i '(emacs-lisp-mode-hook lisp-mode-hook lisp-interaction-mode-hook clojure-mode-hook slime-repl-mode-hook)) (add-hook i '(lambda () (paredit-mode +1))))

14:25 amalloy: jcromartie: oh right. multi-line input becomes hard - you have to use C-o or C-j

14:26 since the input is always well-formed, RET always sends input instead of inserting a newline so you can edit

14:26 jcromartie: hm

14:27 joshua____: amalloy, your here often ;)

14:28 amalloy: joshua____: 100% uptime for at least two weeks :P. my bouncer never logs off

14:28 that doesn't mean i'm actually always here, although i *think* it renames me to amalloy_ when i'm not

14:28 joshua____: I have a question about enlive. If you have lets say one link and you want to transform that into two different links that are seperated by a small bit of text how would you do it? Would you use clone-for?

14:29 amalloy, I saw you become amalloy_afk once.

14:29 amalloy: yeah, that was manual

14:40 joshua____: i have to ask: what's with the orgy of underscores?

14:43 joshua____: amalloy, when I logged on my name was changed to guest because I didn't register it with nickserv or something. So I tried to find a nick that didn't need to be registered. I failed.

14:46 edw: Is there a way to get locals to show up in SLIME?

14:46 In it's debugger, that is.

14:46 s/it's/its/

14:46 sexpbot: <edw> In its debugger, that is.

14:47 amalloy: edw: i think you have to install/use either cdt or debug-repl

14:47 edw: Thanks! So spawn swank from debug-repl?

14:48 amalloy: heh, tbh i have no idea

14:48 that sounds like a good plan though :P

14:48 edw: LOL. Sounds good.

14:51 hiredman: the multimethod's in clojure thread certianly shows how little people understand multimethods

14:51 multimethods

14:52 ~multimethods

14:52 clojurebot: multimethods is what separates the boy from the man.

14:52 amalloy: ~grammar

14:52 clojurebot: Titim gan éirí ort.

14:52 hiredman: it's chouser's or Chousuke's fault

14:53 amalloy: i shouldn't poke fun, since i like the "foo is bar" notation, and i know you have a way to avoid is, but he's so human sometimes that his mishaps look funny

14:53 hiredman: ~clojurebot

14:53 clojurebot: clojurebot has a lot of features

14:54 hiredman: clojurebot: clojurebot | has | a lot of features, most of which are broken

14:54 clojurebot: You don't have to tell me twice.

14:55 amalloy: hiredman: hey, even better than i thought it was. is the second pipe needed for some reason, or just to avoid false positives?

14:59 hiredman: amalloy: just the way I wrote the parser

15:08 tonyl: $mymail

15:08 sexpbot: From: amalloy, Time: 2010-12-14T01:16:17Z, Text: http://is.gd/iHEBY is very unsafe. this is functionally equivalent to your github password; there's a reason github asks you to keep it safe when you create it!

15:08 From: amalloy, Time: 2010-12-14T01:16:48Z, Text: remind me in a couple days to try defacing your account if you haven't fixed it :)

15:10 tonyl: ping amalloy

15:10 thanks for the messages I am going to deal with it

15:29 Nikelandjelo: Swank 1.3 doesn't show stack trace on some exceptions. Is there a way to fix it?

15:32 hiredman: Nikelandjelo: swank is broken on clojure 1.3

15:34 fliebel: Off-topic question that has been bothering me: Does anyone know if the free Amazon ec2 gives you "a free year" or "this year is free"?

15:50 jmatt: fliebel: I think it's a whole year but there are two killer conditions 1) all the good freebies require a new account 2) you have to setup a credit card in case you go over.

16:26 aria42: r2

16:27 tonyl: d2

16:43 ordnungswidrig: hi all

16:43 ohpauleez: hi ordnungswidrig

16:50 alexyk: a barren Fortran-like desert, or just pre-holiday time?

16:50 tonyl: I would say pre-holiday time plus work

16:52 ohpauleez: yeah, pre-holiday

16:52 for me, I'm trying to wrap up changes at work before I go on vacation/staycation

16:52 alexyk: or Tuesday just before 5pm EST

16:53 ohpauleez: ah, yes... it's nearly time for Bad Judgement Tuesday for the east coast

16:53 alexyk: ohpauleez: why is it Bad Judgement?

16:53 ordnungswidrig: can anybody help me with generation permutations by recursion in a special case?

16:53 ohpauleez: it's when you get drunk on Tuesday night

16:54 because it destroys your productivity for the entire week

16:54 amalloy: ~anyone

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

16:54 KirinDave: Man, I keep kicking myself for not making my underlying implementation of clothesline monadic

16:55 ohpauleez: ordnungswidrig: What are you are trying to do and what problem do you see?

16:55 KirinDave: I will have to totally redo my state tests. :\

16:55 Oh well, live and learn.

16:55 ohpauleez: KirinDave: for sure

16:55 amalloy: KirinDave: i feel like i told you to use monads, on account of monads solve everything

16:55 KirinDave: amalloy: I think the prevailing kirindavehate of the day was "why are you using macros and not arrows you fucking tard?"

16:55 The syntax part has worked out beautifully for the most part.

16:56 ordnungswidrig: ohpauleez: I want to create all those permutations for a collection where the first n elements of the permutation satisfy a predicate

16:56 KirinDave: I just did what was easiest at the time, but now I have all these elaborate warts in the test functions to preserve annotation results.

16:56 amalloy: That said, I have learned _so much_ about clojure=scala integration. What works, what does not, etc.

16:56 I find myself yearning desperately for a universal monadic interface and a universal function interface, even if type erasure significantly neuters them.

16:56 ordnungswidrig: ohpauleez: e.g. generate all permutations of (range 10) where the sum of the first n odd numbers is less than the sum of the first n even numbers

16:57 ohpauleez: filtering the set of all permutation will not work because the total number of permutations is to big

16:57 alexyk: KirinDave: didn't I just see you in Scala peddling Sony migrations? Or was it a mirage?

16:57 ordnungswidrig: ohpauleez: thus i want to filter before doing the recursive call

16:58 KirinDave: alexyk: I was not peddling it.

16:58 alexyk: I was asking about it.

16:58 alexyk: KirinDave: yeah, tell it to the G-d of One and Only True JVM FP Language

16:58 KirinDave: alexyk: Callable is so close. :\

16:59 alexyk: Clojure did something wrong to the brain area parsing Scala types and syntax -- it all looks gibberish now :(

16:59 and, OO/FP type system invokes sighs and moaning :(

17:00 ohpauleez: ordnungswidrig: it sounds to me like you need to make something lazy, pass in higher order filtering functions, and then use take/repeat

17:00 alexyk: and endless seq of "why?"

17:00 * alexyk just stating the medical facts, not a language complaints

17:02 ordnungswidrig: ohpauleez: a lazy sequence of all permutation will not work fine. Say, in the example above, you can dismiss all permutations starting with (9 7 0 2). Lazy is good if you need only the first n elements. I have to skip the first n elements :-)

17:03 amalloy: ordnungswidrig: he didn't say all permutations, he said "something lazy". your special lazy-recursive permutation impl can have some way to know when to not generate any more elements,

17:04 ohpauleez: right

17:04 ordnungswidrig: ok, that was wat I thought of

17:05 ohpauleez: yeah, that's the best approach I can come up with

17:05 amalloy: eg, (defn lazy-perms [pred coll] (lazy-seq (when-not (pred <previous elts>) <some recursive stuff>)))

17:05 ordnungswidrig: richt

17:05 right

17:05 ohpauleez: right, and in another impl in my brain, you could trampoline (which you don't have to do if it's lazy)

17:05 ordnungswidrig: I'm fighting with <some recursive stuff>.

17:06 amalloy: ordnungswidrig: so pastie it up. it's tough to debug invisible code

17:06 ordnungswidrig: because i want lexical order of the permutations. In my case the evaluation of the predicate is costly

17:06 ok, I'll paste sth. as soon as it does not work

17:07 Nikelandjelo: '(/ 1 3.75M)

17:07 `(/ 1 3.75M)

17:07 amalloy: Nikelandjelo: & or ,

17:08 Nikelandjelo: &(/ 1 3.75M)

17:08 sexpbot: java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

17:08 Nikelandjelo: amalloy: Thanks

17:13 ordnungswidrig: here we go: https://gist.github.com/741207

17:14 the problem is that the result is nested sequences instead of a seq of permutations

17:16 amalloy: ordnungswidrig: ##(doc mapcat)

17:16 sexpbot: ⟹ "([f & colls]); Returns the result of applying concat to the result of applying map to f and colls. Thus function f should return a collection."

17:16 amalloy: so at the top level you want plain map, so that you get a seq of seqs; at all levels below that, mapcat to keep things from getting deeper

17:17 raek: "CoffeeScript includes a simple build system similar to Make and Rake. Naturally, it's called Cake" :/

17:18 ohpauleez: We will wage a war

17:18 ordnungswidrig: amalloy: so i have another branch for the recursion?

17:18 ohpauleez: I don't even use Cake

17:18 ordnungswidrig: amalloy: I got it: always use mapcat but on the lowest level return [previous]

17:18 technomancy: raek: don't forget Cake the PHP framework

17:19 amalloy: ordnungswidrig: that won't work at the outermost level

17:19 because you'll get [1 2 3 1 3 2] instead of [[1 2 3] [1 3 2]]

17:19 so you need to do that, *and* at the outer level just use map

17:19 lancepantz: we figured they can't have both coffee and cake

17:19 ordnungswidrig: amalloy: therfor I return [previous] if rest is empty

17:19 clojurebot: Alles klar

17:19 lancepantz: i mean come on, pick one

17:19 ordnungswidrig: amalloy: I updated the gist

17:20 dnolen: I actually work at the Times with the developer of CoffeScript. Nice guy. I don't see much overlap between CoffeeScript users and Clojure users.

17:21 amalloy: ordnungswidrig: and have you tried it out? i think your change is necessary but not sufficient, so to speak

17:21 ordnungswidrig: amalloy: I tried it and it works

17:21 amalloy: well then

17:21 mapcat to the rescue

17:21 ordnungswidrig: amalloy: I always forget about this beast

17:22 amalloy: ordnungswidrig: i often do too. you caught me at the right time, it seems

17:22 technomancy: dnolen: why's that? seems like a natural match.

17:22 ordnungswidrig: I need an emacs function that reminds me of mapcat if I work too long on a function using map

17:22 technomancy: nicer language on a widely-deployed runtime

17:23 amalloy: ordnungswidrig: once you've written it, send it to me so i can use it for (for)

17:23 ordnungswidrig: amalloy: the emacs function=

17:23 ?

17:23 amalloy: yeah

17:24 dnolen: technomancy: it's pretty traditionally OO in design. I dunno, it's not coming from an FP point view at all.

17:24 raek: at least anonymous functions has a short syntax...

17:24 dnolen: I like it, but I also have no problems just writing plain old JS in FP style either.

17:25 ordnungswidrig: is there any work ongoing on compiling something like clojure to js? beside cic?

17:25 amalloy: $google clojurescript

17:25 sexpbot: First out of 52 results is: clojurescript at master from richhickey/clojure-contrib - GitHub

17:25 https://github.com/richhickey/clojure-contrib/tree/master/clojurescript/

17:26 amalloy: i'm not sure how sophisticated it is, but...

17:28 ordnungswidrig: oh nice

17:28 amalloy: oh, and you should look at the one under clojure, not richhickey. google just wno't let go of that old, dead repo

17:35 will_l: I was trying to use memoize on a recursive method, and I'm curious about this behavior: https://gist.github.com/741240

17:38 dnolen: now if CoffeeScript supported Dylan style macros, http://www.opendylan.org/books/drm/Rewrite_Rule_Examples

17:38 maybe I'd get excited

17:40 ordnungswidrig: is there a function to check if a seq is sorted?

17:40 amalloy: &(doc sorted?)

17:40 sexpbot: ⟹ "([coll]); Returns true if coll implements Sorted"

17:40 amalloy: will_l: memoize creates a new copy of the function that is memoized. it can't know that foo is calling (foo) and somehow redirect that to (memoized-foo) instead

17:40 ordnungswidrig: (= coll (sort coll)) will have O(n*log(n)) but I think O(n) will do?

17:42 will_l: amalloy: so when a function is defined, it grabs hold of what it sees? Clojure doesn't do method lookup every time?

17:42 amalloy: ordnungswidrig: (every? #(apply > %) (partition 2 1 coll)) looks like a good start

17:42 will_l: the function gets compiled, yes

17:42 will_l: amalloy: thanks

17:43 amalloy: ordnungswidrig: (modulo implementation details like using the right comparator)

17:44 will_l: but i'm not sure you got what i meant. the point is not that foo calls (foo) and doesn't look up any new definitions of foo; it's that the definition of foo remains unchanged, and you create a new function called mem-foo

17:45 will_l: amalloy: oh. My confusion was that I was redefining foo as mem-foo, so I thought all references to the old foo were gone

17:46 amalloy: will_l: ah. then you did indeed get my point; the other thing you said was true, and is the relevant thing here

17:46 you can force a lookup every time by calling the var instead of the function directly: (#'foo bar)

17:46 will_l: amalloy: is there a more idiomatic clojure way to do what I was trying to do?

17:47 ordnungswidrig: nice

17:48 dnolen: huh, Sealing in Dylan is pretty interesting, http://www.opendylan.org/books/drm/Sealing

17:49 amalloy: will_l: i try to avoid global memoization, since it means nobody can use your function lazily on some large number

17:50 will_l: amalloy: thanks!

17:50 amalloy: i'm not sure what you're trying to compute; you can often do stuff like this using ##(doc iterate) in some sneaky ways, but if you're just learning, you're probably better off avoiding sneakiness

17:50 sexpbot: ⟹ "([f x]); Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"

17:52 will_l: amalloy: it was for http://projecteuler.net/index.php?section=problems&id=92

17:54 amalloy: will_l: in that case, i'd forget about memoization; i doubt you're gaining that much time, and it's costing nontrivial memory

17:55 will_l: It took it from >2 min and running out of heap space to 20 seconds

17:56 ninjudd: does anyone know if server mode GC's PermGen (or more specifically classes)?

17:57 amalloy: will_l: no way it should run out of heap space; i'll throw something together and see what happens

18:00 will_l: amalloy: here's the full thing I did: https://gist.github.com/741240#file_my_full_solution.clj

18:06 amalloy: will: try (->> (range 1 1e4) (map #(iterate next-chain %)) (map #(take-while (complement #{1 89}) %)) (map (juxt identity count)))

18:07 should tell you the length of every chain from 1 to 1000; you can easily modify it to tell you instead whether they end with 1 or 89

18:08 er, will_l: ^^ (i guess my version doesn't include the last number; i leave that as an exercise for the reader)

18:11 will_l: amalloy: i'm looking at it now, thanks

18:17 amalloy: thanks for your help

18:38 duncanm: in lein 1.4, how do i set compiler flags for javac?

18:40 amalloy: duncanm: it's java-opts to set java options, right? javac-opts might well work

18:42 duncanm: amalloy: doesn't look like it

18:42 amalloy: technomancy: okay, i checked that the computer was plugged in. now you debug the real problem for duncanm

18:43 duncanm: amalloy: i checked the src, it should be javac-options, lemme see if it works

18:43 oh, so javac-options is not in [...] form

18:44 eek, i need to know what a lancet task spec looks like?

18:44 i just want -Xlint:deprecation

18:45 amalloy: duncanm: i also know lein respects the JAVA_OPTS environment variable; try setting JAVAC_OPTS?

18:46 duncanm: doesn't look to me it's working

18:46 i'd be happy if there's a verbose mode and i can just try the javac command line myself

18:46 amalloy: a verbose mode?

18:47 lancepantz: duncanm: i think you can use hooks to redefine the compile task

18:48 duncanm: oh well

18:48 i typed out the -cp part, i can see what's deprecated now

18:48 technomancy: duncanm: :javac-opts is supposed to be a map it looks like

18:49 but I don't really know; I didn't write the javac task (since I don't know java)

18:52 cky: duncanm is alive?!

18:52 lancepantz: duncanm: wanna try with cake?

18:52 cky: duncanm: People in #scheme have been speculating on your fate. :-P

18:53 duncanm: cky: heh

18:53 cky: been busy with work

18:53 cky: Awwww....

18:53 duncanm: cky: is Taylor still active in the channel?

18:53 cky: Ye-.

18:53 Yes.

18:53 duncanm: ah, i haven't heard from him in a while

18:53 lemme go to #scheme ;-P

18:54 cky: :-P

18:54 technomancy: Riastradh?

18:54 if so give him a high-five for me for paredit 22.

18:54 duncanm: technomancy: yeah

18:55 lancepantz: duncanm: in cake, you can set the :java-compile key in project.clj to a map of the options specified at http://ant.apache.org/manual/Tasks/javac.html

18:55 duncanm: lancepantz: what's cake?

18:55 other than a tasty treat?/

18:56 lancepantz: a lein alternative, it should be compatible with the same project.clj

18:56 https://github.com/ninjudd/cake

18:56 duncanm: hmm, competition!

18:57 lancepantz: competition is bad!

18:57 cky: lancepantz: That's what Oracle wants you to believe. :-P

18:58 lancepantz: hahah

19:24 duncanm: how should i test that a list consists of the same pair repeating over and over again?

19:24 i tried (assert (= l (cycle (first l)))) but that's not quite it

19:24 i tried (assert (= l (cycle [(first l)]))) too

19:24 amalloy: duncanm: you want to test an infinite number of pairs?

19:25 duncanm: amalloy: l is finite, right?

19:25 amalloy: ah. you mean it should consist of the same pair repeated N times, for some finite N? it reads like you meant forever

19:25 duncanm: right

19:25 it's finite

19:25 sorry

19:26 technomancy: duncanm: (= 1 (count (set l)))

19:26 duncanm: technomancy: cute!

19:27 amalloy: (apply = l (cycle (take 2 l))) looks good

19:27 * technomancy idly ponders the addition of a one? predicate to keep zero? from getting lonely.

19:27 amalloy: technomancy: that tests that it's a single item N times. i thought he meant [a b a b], not [[a b] [a b]]

19:28 i guess my version needs a (take (count l)) around the cycle

19:28 technomancy: will = short-circuit on a lazy seq once it detects a different element?

19:28 amalloy: technomancy: yeah, it will

19:28 technomancy: ,(java.util.Date. 0)

19:28 clojurebot: java.lang.IllegalArgumentException: No matching ctor found for class java.util.Date

19:29 technomancy: huh; coulda sworn...

19:29 amalloy: &(java.util.Date. (long 0))

19:29 sexpbot: ⟹ #<Date Wed Dec 31 16:00:00 PST 1969>

19:29 technomancy: *facepalm*

19:30 * amalloy doesn't make the rules

19:33 technomancy: if you did they wouldn't be so achingly stupid.

19:34 amalloy: technomancy: tell me about it. i've been dealing with java.util.Date/Calendar/UUID for weeks at work

19:44 hiredman: ping?

19:44 clojurebot: PONG!

20:20 defn_: amalloy: defprotocol, no?

20:20 amalloy: defn_: what?

20:21 defn_: isn't fixing java.util.Date a defprotocol away?

20:22 amalloy: i...don't really understand what you're saying, but i'm working with them in java anyway, not clojure

20:24 defn_: oh...nevermind...

20:24 I just saw a talk on using defprotocol to make java's Date and Time sane.

20:24 sean devlin gave it.

20:33 hiredman: defn_: I doubt the ability of protocols to do that

20:33 it might miake them less painful

20:35 technomancy: sane is a strong word

20:35 defn_: i must be wearing orthopedic shoes

20:35 because i stand corrected

20:38 gfrlog: (defn map-from-fn [f ks] (zipmap ks (map f ks)))

20:38 if that were in clojure.core I would use it all the time

20:38 amalloy: gfrlog: it's in clojure.contrib.generic.functor

20:38 gfrlog: I knew it must be somewhere

20:39 thx

20:39 amalloy: or wait, is it? i'm thinking of fmap, which i guess is different

20:39 gfrlog: yeah that looks different

20:40 my idea would be even cooler if it was lazy. but that would probably require a different underlying map class

20:40 amalloy: gfrlog: when i was learning clojure and proposed adding this, someone (hiredman? laujensen?) said that it's usually a bad idea

20:40 gfrlog: I can imagine the argument that you should just use the function 'f' instead of the map

20:40 but that doesn't work all the time

20:41 I'm not sure why else it would be a bad idea...

20:41 amalloy: another neat impl is (into {} (map (juxt identity f) x))

20:41 gfrlog: yeah

20:41 but that's only because using juxt is always clever :)

20:42 amalloy: it's also basically the same as memoize

20:42 gfrlog: oh? is into lazy?

20:42 ,(doc into)

20:42 clojurebot: "([to from]); Returns a new coll consisting of to-coll with all of the items of from-coll conjoined."

20:42 amalloy: nono, i mean the whole notion

20:42 gfrlog: well not quite

20:42 you can pass a map somewhere, and the advantage is that it takes the keys with it

20:43 try passing a memoized function to (json-str)

20:46 map-from-fn is a terrible name though

20:53 xiackok: hi everyone

20:54 gfrlog: can any function definition be expressed as a combination of higher-order functions?

20:55 xiackok: i trying to get slime working with clojure for 6 hours. now i eating my brain

20:56 cky: gfrlog: Sure! (define cadadr (compose car cdr car cdr)). :-P

20:56 gfrlog: (That's not Clojure, but you get the gist of that.)

20:56 gfrlog: what about #(% %)

20:56 xiackok: can anyone help pls

20:58 gfrlog: I suppose (apply x [x]) would work

20:58 no wait

20:58 that doesn't return a function...:(

20:58 hiredman: gfrlog: SKI says so

20:59 gfrlog: hiredman: given your name was brought up in my conversation from 5 minutes ago, I'm not sure if you're referring to that or my current mumblings

21:01 ooh

21:01 looked up SKI

21:01 think I have it all sorted out now

21:01 still working on #(% %)

21:29 duncanm: is there a way to generate a pom.xml from a lein project?

21:32 sigh, i did a lein pom and netbeans still can't see it

21:38 duck1123: Hey guys

21:40 bhenry: hi duck1123

21:40 duck1123: There was a thread on the list today about binding and lazytest, and stuarts suggestion was to use do-it, but my problem is that I can't put multiple exects inside the do-it and make the story work

21:40 any heavy BDD-types around?

21:42 would it be possible to hook the 'it' function so that I could wrap it with with-database

21:54 is there a version of every? that fails if the collection is empty?

21:56 dnolen: I never remember, is apply lazy?

21:57 I would imagine not.

21:57 amalloy: dnolen: i think it's lazy enough to not realize all &rest params

21:57 &(apply + (range 1e4))

21:57 sexpbot: ⟹ 49995000

21:58 dnolen: amalloy: ah great.

21:59 defn_: anyone here intimately familiar with the innerworkings of Dylan?

22:00 I am interested in the fact they seemed to keep s-expressions even though they switched to a more algol-style syntax

22:00 amalloy: defn_: mumble rhythmically while music plays

22:00 defn_: hahaha

22:00 I think it's an interesting language

22:00 Dylan seems like the last effort to "bridge the gap"

22:02 the algol-style syntax -- it seems actually quite a lot like Ruby in some ways -- I wonder what tradeoffs there were in that decision

22:03 amalloy: defn_: have you asked in #dylan?

22:04 it seems like they'd know more than we do

22:14 dnolen: are rest vars allowed in protocol signatures ?

22:14 amalloy: dnolen: i don't think so

22:14 dnolen: grrr

22:15 amalloy: dnolen: protocols are for low-level impl stuff. define your protocol to take a seq as its last argument, and then provide the &rest sugar in the library layered over the protocol

22:17 dnolen: amalloy: I don't consider protocols very 'low-level'. I'm looking forward to that getting fixed.

22:18 amalloy: getting what fixed? i doubt you'll get rest args; the point of protocols is fast java interop, and the two won't play nice

22:18 if you want fancier stuff, you probably want an interface or a multimethod

22:21 dnolen: amalloy: interfaces are less fancy then protocols

22:21 amalloy: I recall rhickey mentioned rest vars, destructuring missing from protocols.

22:22 hiredman: dnolen: you should look at protocols in core like internal reduce

22:23 the use doesn't call the functions defined in internal reduce

22:23 the user calls reduce

22:24 the point is protocols are an extender/implementer interface, with a set of functions built on top that the consumer of the library uses

22:25 dnolen: hiredman: that's useful. Holy crap ... I had no idea that nil could be used as protocol.

22:25 hiredman: the set of functions that operate on sequences can be view like this

22:26 dnolen: I'm happy to say that in my use case at least going from TCO code to lazy sequences isn't any slower, and I don't get any stack overflows.

22:26 hiredman: seq being a protocol, reduce/map/filter being what the consumer normally uses

23:20 amalloy: given an ascii/utf number (eg 10), how do i get a char (eg \newline)?

23:22 update: i'm an idiot, it's just (char 10) and i had a bug elsewhere

Logging service provided by n01se.net