#clojure log - Oct 08 2011

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

0:27 no_mind: I am getting this error on using compile "java.lang.ClassNotFoundException: clojure.contrib.json.Read_JSON_From" . Does compile has a dependancy on json ?

0:57 amalloy: no_mind: the code you're trying to compile does

1:00 no_mind: amalloy: but the code I am compiling desnt use json

1:02 amalloy: i think that you are wrong

1:04 no_mind: amalloy: my code is not using json, maybe some other lib is. But at the same time I have clojure.contrib.json installed

1:04 I am using congomongo, maybe that is using json.;..

1:09 amalloy: a grep on the source code directory shpws this "Binary file ./classes/clojure/contrib/json/Read_JSON_From.class matches". So Why the error ?

1:09 amalloy: *shrug*

1:10 no_mind: clojure community is turning un helpful day by day...

1:10 amalloy: perhaps you tried to add some new libraries to the classpath without restarting the jvm

1:11 no_mind: I fired a fresh repl to compile

1:11 amalloy: no_mind: this is a volunteer helpforce. nobody pays me to know what causes compile errors on your machine, and i simply don't know given the information "compile fails due to json"

1:13 no_mind: no one pays anyone all over IRC to help anyone...

1:14 amalloy: yes, indeed. so when nobody jumps out of the bushes with a solution to your problem, complaining that the community is becoming unhelpful is sickening

1:14 no_mind: what I trying to do is already open sourced and available on github.. No one is paying me to do this...

1:14 I am asking this for couple of days now...

1:15 amalloy: unlucky. perhaps nobody knows the answer, or you're not giving any information

1:15 s/any/enough

1:15 lazybot: <amalloy> unlucky. perhaps nobody knows the answer, or you're not giving enough information

1:21 no_mind: I am using IRC for over a decade now, so I know how to supply enough information for sure

1:24 rimmjob: the channel is just slow at this time

1:29 could you post a link to the source?

1:37 zodiak: no_mind, do a grep -l for contrib.json across the whole project. I assume you have lein dep'd and also have your git clone/source in checkouts so everything related get's searched ;)

6:49 PleajureSeeker_: Hey, I'm a noob in Clojure and I'm having troubles with the basics of (gen-class) - can someone help me?

7:09 eliOcs: hi guys!

7:09 anyone active around?

7:10 can someone help me with the swank installation

7:10 I

7:11 I've been following the installation instructions:

7:11 #

7:12 Install clojure-mode either from Marmalade or from git.

7:12 lein plugin install swank-clojure 1.3.3

7:12 From inside a project, invoke M-x clojure-jack-in

7:14 khaliG: eliOcs, yup and

7:14 eliOcs: should I be alble

7:14 to connect via de SLIME command

7:14 I dont get de REPL

7:14 khaliG: no the clojure-jack-in takes care of that

7:14 what happens when you type it?

7:15 eliOcs: compiles a bunch of files

7:15 but it doesn't take me to a new buffer

7:15 or anything

7:16 khaliG: yea it should split the screen and show a repl on the bottom

7:16 eliOcs: wow

7:16 It did it now

7:16 khaliG: nice :)

7:16 eliOcs: the first time it only did the compile

7:16 ok this is odd

7:16 thansk khaliG

7:16 khaliG: np

7:16 eliOcs: feel stupid now

7:16 hahah

7:25 when you finally get the emacs with lein to work it seems a great way to develop

7:28 zilti: eli0cs: Do you have elein installed?

7:32 eliOcs: yep

7:32 I've installed lein

7:36 zilti: No, elein is a script for emacs to use lein with emacs

7:37 eliOcs: oooh

7:38 havent installed that yet

7:38 I'll google it a give it a try

8:20 eiro: (hello "world")

8:22 Arafangion: (hello "eiro")

8:52 daniel___: whats the equivalent in clojure of x = (1 2 3) ?

8:52 (define x 1 2 3)?

8:53 something like that

8:53 Bronsa: (def x '(1 2 3))

8:53 daniel___: merci

8:54 and what does the ' mean

8:54 Bronsa: it's synax macro for quote

8:55 so that clojure doesnt treat (1 2 3) as a function call

8:55 daniel___: i see, but why would it?

8:55 is 1 a function?

8:55 Bronsa: indeed it is not

8:56 but first elements of lists are always treated as if they were a function

8:56 in all lisps

8:56 daniel___: ok

8:56 Bronsa: if you dont want to syntax quote you either need to construct the list with (list ...) or use a vector

8:57 daniel___: keep in mind that if you syntax quote, none of the fields of the list will get evalated

8:57 daniel___: ok, thats what i want i think

8:58 Bronsa: then (def x [1 2 3 whatever])

8:58 daniel___: (def ratings '(map rating args)) will give me an 'array' with the ratings of whats in my list

8:58 Bronsa: no

8:58 it will bind ratings to a list with three symbols

8:58 map rating and args

8:58 daniel___: ah shit, ofc

8:59 Bronsa: if you want it to be evaluated you need to remove the quote

8:59 daniel___: so in this case i want []

8:59 Bronsa: no

8:59 in this case you want (map rating args)

8:59 daniel___: ok right sorry

8:59 [] is a vector

8:59 Bronsa: so taht x will be bind to the result of applying map to rating and args

8:59 daniel___: and it is equivalent to '() in this scenario?

8:59 Bronsa: *that

8:59 well no

8:59 syntax quoting can be done on vectors too

9:00 and it prevents every element to be evaluated

9:00 a vector is different from a list (apart from performance details) in wich it doesnt treat the first element of itself as a function call

9:01 you can see the difference here

9:01 ,[map identity 1]

9:01 clojurebot: [#<core$map clojure.core$map@149e15b> #<core$identity clojure.core$identity@1c81de> 1]

9:01 Bronsa: ,(map identity 1)

9:01 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

9:01 Bronsa: fuck

9:01 ,(map identity [1])

9:01 clojurebot: (1)

9:01 daniel___: ok, thanks Bronsa

9:01 Bronsa: np

9:01 daniel___: wait, is there a repl in this channel?

9:02 ,(+ 1 2)

9:02 clojurebot: 3

9:02 daniel___: :D

9:02 Bronsa: you can query clojurebot too

9:10 mbac: i watched stuart halloway's presentation on clojure and simplicity and now i'm confused

9:10 maybe it's because i'm a clojure newb

9:12 here's what i understood. i have a rigorous definition of simple. clojure is simple. ???. clojure rocks!

9:12 did i miss anything else?

9:21 https://blip.tv/clojure/stuart-halloway-simplicity-ain-t-easy-4842694 <- this presentation

9:26 cemerick: mbac: What was confusing to you?

9:28 mbac: the feeling that i missed something

9:29 cemerick: it's hard to respond to that

9:29 mbac: right. so, what if he had done s/clojure/lisp/g

9:29 it's still mostly the same talk. yes?

9:30 with the exception of vector-bindings

9:30 those are EVEN SIMPLER than what other lisps do

9:31 cemerick: Not really. Lisp doesn't address the same issues Clojure does re: concurrency, state, data structures, etc.

9:31 Lisp, broadly speaking, that is.

9:31 mbac: maybe i'm having a problem because i'm a lisp newb

9:32 cemerick: Lisp is good, but homoiconicity doesn't solve everything.

9:33 mbac: what's novel about clojure wrt. lisp?

9:33 cemerick: mbac: please read: http://clojure.org/rationale

9:34 mbac: "Defaults to immutability"

9:34 ok that's exciting. i thought all lisps did that

9:34 cemerick: goodness, no

9:35 mbac: how do people get off calling lisp a family of functional programming languages when immutability isn't default?

9:35 cemerick: In very rough terms, all you need to be a lisp is homoiconicity and first-class functions.

9:35 "functional" is a very, very nebulous term

9:36 mbac: to me it means no side-effects

9:36 cemerick: Some people would argue that only statically-typed ML-style languages are functional.

9:36 mbac: and mutability menas programming with side-effecs

9:36 strong static typing is orthogonal to functional programming

9:36 cemerick: some would argue that immutability is orthogonal to FP

9:37 gtrak``: i thought functional meant functions

9:37 cemerick: Right, that's about the only common ground. :-)

9:37 mbac: pure functions

9:37 fliebel: I thought functional means "does concurrency well" ;)

9:37 cemerick: mbac: yeah, zero consensus on that.

9:37 mbac: pure functions and mutability can't co-exist?

9:38 what? really?

9:38 gtrak``: mbac, of course not

9:38 pure functions have no side effects

9:38 mbac: yes, i agree

9:38 cemerick: Insofar as most would want to say that scheme is functional, we have to admit that e.g. Javascript is as well on purely technical terms. A lot of it has to do with accepted idioms.

9:38 mbac: we have consensus :)

9:38 gtrak``: the part that coexists isn't a pure function

9:39 mbac: In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data.

9:39 no consensus? it's the first line in the wikipedia article!

9:40 cemerick: Wikipedia being the end-all, be-all, of course. :-)

9:40 mbac: duh

9:41 that's why i'm citing it :)

9:41 cemerick: mbac: If you look at the 'Type Systems' section in that article, it's clear the whole thing is constructed from an ML perspective.

9:43 fliebel: Are there any NXT owners here? I'm thinking about writing a compiler, so I wonder if there is any "market".

9:44 mbac: alright. so, if he had done s/clojure/scheme/g it's mostly the same talk, except again vector-bindings

9:45 cemerick: except scheme isn't immutable by default, has no unified data structure story, no state abstractions, etc.

9:45 mbac: OK! unified data structure story. i want that

9:46 * mbac watch https://blip.tv/clojure/clojure-data-structures-part-1-714056

9:59 Leeni: hey guys, take a look at this: http://shootout.alioth.debian.org/u64q/performance.php?test=fannkuchredux

9:59 why does clojure solution use only 75% of CPU?

10:02 fliebel: Leeni: No idea. Have you tried running it yourself?

10:03 * gfredericks is surprised there's no major google hit for "clojure vs scheme"

10:06 cemerick: gfredericks: Not really a big point of comparison; I'd be surprised if such a hit existed.

10:06 gfredericks: cemerick: I'd think there'd be plenty of shallow interest though, scheme being one of the two major pre-clojure lisps

10:07 cemerick: Well, there's *lots* of schemes, which makes things more diffuse.

10:07 gfredericks: i.e., I think lots of people would google it, whether or not it'd make an existing article. I suppose googlers don't will articles into existence though.

10:07 oh I did not know that.

10:07 cemerick: yeah, there's dozens of 'em

10:07 scheme is an idea

10:07 gfredericks: I guess now there are lots of clojures too huh :/

10:07 lots == 3

10:08 cemerick: sorta

10:08 gfredericks: sorta

10:08 cemerick: They all have the same objectives, as reasonable given their host platforms.

10:08 gfredericks: right

10:08 cemerick: Which is not true for the various schemes.

10:09 gfredericks: s/existing/interesting

10:09 the phrase "high-level typo" just popped into my head

10:13 Leeni: fliebel: also what's the deal with slowness. It uses java arrays and runs on clojure 1.3 yet 4 times slower than java

10:14 gfredericks: Leeni: they're not accidentially including the clojure load time in the measurements are they?

10:15 Leeni: I don't think so, otherwise java would not get so close to C in terms of time

10:15 gfredericks: Leeni: I guess I could imagine them accounting for jvm startup time but not clojure

10:18 bsod1: gfredericks: what do you mean by `lots of clojures` ? sorry I'm new at clojure..

10:19 gfredericks: bsod1: I was just referring to the 3 platforms it has been implemented on: jvm, clr, and javascript

10:19 zilti: Dynamic languages always are slower than static ones. Especially if they aren't aot compiled.

10:19 fliebel: It took me a couple of seconds to realize we have an CLR impl too.

10:20 gfredericks: as cemerick pointed out, they're really a lot more unified than is implied by calling them "lots of clojures", where the differences between them correspond to the differences between the platforms

10:20 bsod1: gfredericks: is javascript implementation ClojureScript?

10:20 gfredericks: bsod1: yes

10:20 fliebel: yeah I've never really heard of anybody using it :)

10:21 cemerick: zilti: s/always/often

10:22 zilti: cemerick: I'd actually like to see a counter-example, never seen any.

10:23 gfredericks: zilti: well you could certainly construct one just for the sake of a counterexample

10:24 fliebel: zilti: Counter example to what?

10:24 gfredericks: fliebel: "dynamic always slower than static"

10:24 cemerick: zilti: Such comparisons are often flawed because of algorithmic differences enabled/required by the respective languages, and trivial comparisons almost always favor static compilation strategies because of the limited latitude for runtime optimization, etc.

10:24 I've written Clojure that's faster than the corresponding java, tho.

10:25 gfredericks: I think those performance tests should include development time :)

10:30 zilti: Of course, since Clojure can be compiled aot it can reach the speed of Java. As for Clojure speed faster than Java speed, I guess that has a lot to do with the involved libraries? Not that I want to say "dynamic is slower, dynamic sucks". It has its technical reasons, e.g. about having to calculate position and length of data in ram

10:31 gfredericks: once the hardware people stop innovating we can all sit down and take a few decades to make our high-level stuff as fast as is theoretically possible.

10:31 * gfredericks has a pretty boring view of the future, apparently

10:33 fliebel: gfredericks: I'd like to hear the hardware people on that. "Once the software people stop mucking around, we can take a few decades to develop super fast hardware.

10:34 gfredericks: lol. I bet they get peeved that they have to support the same arbitrary instruction set indefinitely

10:35 zilti: x86 was considered to be outdated almost 20 years ago

10:37 gfredericks: I wonder what kind of speedup is possible with a fresh redesign

10:37 also I wonder what the implications on consumer computing would be if FP was moved off-chip

10:40 I guess that would kick javascript in the gut

10:43 Leeni: no man, I'm just asking where's the slowup since it's using java arrays and why does it only use 75% of cores. Not asking for instance why is it grotesquely memory inefficient because that's par for the course for clojure

10:52 or this: http://shootout.alioth.debian.org/u64q/benchmark.php?test=knucleotide&lang=all

10:53 clojure always has shitty cpu utilization

10:54 zilti: Leeni: One could as well ask why Scala is 7 times slower in the benchmark.

10:54 gfredericks: as someone who's not an expert, I would think that "grotesquely memory inefficient" could lead to "shitty cpu utilization", since the former could reduce the effect of memory caching

10:55 Leeni: zilti: because it uses only one core

10:55 fliebel: Leeni: The other run on multiple cores?

10:55 Leeni: if you are talking about the first benchmark

10:56 or are you talkng about the second one

10:56 look at last column CPU load

10:56 shows cpu load for cores

10:56 clojure is always around 75% load per core and I don't see why...

10:57 zilti: Second test is funny. g++ 3.86 sec, gcc almost 20 secs, clojure 9 minutes...

10:58 Leeni: clojure has 60 seconds I believe

10:58 zilti: And, to be honest, I don't really trust these benchmarks. Look at the different Scala tries. First attempt 37 seconds, fourth attempt "failed". huh?

10:59 Leeni: different code

10:59 zilti: Leeni: no, first attempt of closure in the second benchmark is indeed 9 minutes

10:59 Leeni: those are not attempts

10:59 zilti: versions?

10:59 Leeni: different submitted solutions

11:00 generally the best clojure one is ugly as hell with loop-recur, array operations and typehints all over the place

11:00 still takes twice as much RAM and four times as much time as Java in general

11:01 idiomatic clojure code is 9 minutes yes...

11:01 arohner: emacs masters, what is the name of the feature where comments in your source code get executed by emacs? typically used for formatting and things?

11:05 Arafangion: arohner: #emacs is awesome. :)

11:06 I notice that Clojure actually has a respectable position in that benchmarks chart... Particularly #5.

11:06 Although it does have a lot of hints.

11:07 pdk: where's this benchmarks chart

11:07 language shootout?

11:07 Arafangion: Yeah, that one.

11:08 It would be interesting to see that shootout if the startup delay was factored out.

11:08 Such that the routine itself was compared.

11:09 Leeni: compare it with java

11:09 same startup

11:10 Arafangion: Leeni: Notice that the java code has fewer classes needed, it probably doesn't need to load any support used by Clojure or anything.

11:10 Leeni: and I don't think startup delay is factored in

11:10 Arafangion: No, I doubt very much that it is.

11:11 Leeni: or look at regex-dna test

11:12 Arafangion: Clojure is much closer to Java there.

11:13 Hmm, no, it's still roughly 10x slower.

11:13 But that Java code there is horrible.

11:14 Interesing how C is consistently very high up.

11:16 Hmm, "all shootouts" and "all languages" gives a /very/ interesting chart.

11:17 Clojure is /always/ slower than C++.

11:17 Leeni: no shit lol

11:17 you don't need a shootout to figure that one out

11:17 Arafangion: Leeni: Well, it's interesting because it's not always slower than C.

11:17 The best clojure is faster thaan the worst C.

11:18 gfredericks: the worst C has sleep calls in the inner loop

11:18 Leeni: I think the negative surprises are: how much slower it is than java, how ugly the code for fastest case is and how low the CPU utilization always is

11:19 Arafangion: The low CPU utilization would be the only thing that concerns me there.

11:20 Note that I have yet to actually /use/ clojure.

11:20 Leeni: :)

11:21 Arafangion: Unlike the shootout folks, I actually know how to optimise.

11:21 Leeni: I think the big letdown is that in java I can write idiomatic code and I am pretty sure I am within 30% of speed of hand optimized code, in clojure with idiomatic code you can be pretty certain you are running code three times slower than optimized code

11:22 Arafangion: Leeni: That's a point, however, that said, my favorite langauge is python.

11:22 And I'm sure real-world clojure code is probably faster.

11:22 Leeni: not really

11:23 operations on collections are expensive

11:23 Arafangion: Unfortunate. :(

11:23 Leeni: iterating though a sequence is expensive

11:23 Arafangion: In python, doing a function call is expensive.

11:24 Leeni: just walking through a sequence and printing results will result in tons of memory allocations

11:24 Arafangion: That's unfortunate - whose fault is that? Clojure, or the VM?

11:24 Leeni: clojure

11:25 Arafangion: Well, someone will just have to optimise clojure a bit more. :)

11:26 Leeni: this is impossible... you need to allocate an object for each member of a sequence otherwise you'll be breaking the abstraction

11:26 Arafangion: Perhaps you could reuse objects.

11:26 * Arafangion is talking out of his ass, though.

11:27 Leeni: sequences must support ability to pass tails of sequences around

11:27 thus you need to allocate a sequence object for each element of sequence you realize

11:28 Arafangion: I'm sure they could still be reused. Perhaps have it copy the iterator on-demand, as well as reusing a shared pool of iterators.

11:28 Leeni: this is where clojure is very different from java loops or Iterable

11:28 Arafangion: Well, no, that makes sense.

11:28 Leeni: bascially imagine a linked list

11:29 Arafangion: I can imagine it, but even so, I'm sure that there's going to be a typical use case that you can optimise for.

11:29 Leeni: (range 10) will produce 10 linked list(sequence) nodes

11:29 Arafangion: You can't produce them lazily?

11:29 (Which is what I'm getting at)

11:29 Leeni: yes lazily

11:30 zilti: They are produced lazily

11:30 Leeni: but imagine you feed them into a function as a sequence of indexes

11:30 they will all get realized inevitably

11:30 Arafangion: You can't, say, pre-generate 100 linked lists and reuse them, lazily initialising more if you have the need?

11:30 zilti: List = single-linked list, Vector = Java-Array

11:30 So why is Vector still so much slower?

11:30 That should be easy to optimize

11:31 Leeni: in any case where java would have iterable that returns 10 Integer objects, clojure has 10 sequence objects allocations

11:32 in java ArrayList is faster at adding elements in the front than LinkedList up to I think 10000 or 100000 elements, even though it's O(n) for arraylist and O(1) for linked list. Simply because linked list add results in an allocation for each element added

11:32 Arafangion: Seems that the obvious solution is to reuse the sequence objects.

11:32 zilti: I guess that's because all operations on collections are only realized using first and rest functions

11:33 Leeni: zilti clojure vector is not array, it's a tree with 20 branching

11:33 hence it's really expensive to modify, because you have allocation of nodes again

11:33 (among other things)

11:34 zilti: Huh, that's strange cause in the screencast he says otherwise (Clojure for Java programmers)

11:35 Leeni: i;m 100% it's a tree

11:35 Arafangion: Just looked at the source for sequence.

11:35 I notice that it's a clojure implementation, not Java.

11:36 https://github.com/clojure/clojure/blob/f5f827ac9fbb87e770d25007472504403ed3d7a6/src/clj/clojure/core.clj#L2350

11:36 Leeni: java doesn't have sequence, only Iterable interface

11:36 dnolen: Leeni: it's not *that* expensive to modify. plus you get all the safety benefits.

11:36 Leeni: and it's not 20, it's 32

11:36 Arafangion: Leeni: That doesn't follow.

11:37 Leeni: Well, yes, Java doesn't have a sequence type, but that doesn't mean that it can't.

11:37 Leeni: I'm sure you'd be able to write one in Java? That was the observation I made, that it was Clojure.

11:37 Leeni: wouldn't change anything

11:37 I mean if it was the same algorith

11:38 Arafangion: A Java implementation is *unlikely* to use the same algorithm!

11:38 Leeni: problem is that sequences as they are conceptually produce a ton of allocations on first walkthrough

11:38 Arafangion: map does even more allocations.

11:39 Leeni: point being?

11:39 dnolen: fortunately the JVM is really good at allocations.

11:39 Leeni: map isn;t known for being fast

11:39 dnolen: still way way way worse than not doing allocations at all

11:40 dnolen: Leeni: in many applications the allocations hardly matter. Ever.

11:40 Leeni: it's why arraylist is way faster than linkedlist

11:40 dnolen: Leeni: it's easy to use a better data structure if the allocations matter.

11:40 Arafangion: dnolen: You have more or less the same cost for allocations in Java as you do in other environments.

11:41 dnolen: But deleting the objects is effectively free.

11:41 Leeni: allocations always matter

11:41 they produce large slowdowns

11:41 Arafangion: Not if you pre-allocate.

11:42 Python, for instance, will pre-allocate and share integer objects.

11:42 (The first hundred or so, anyway)

11:42 Leeni: java has that too

11:42 Arafangion: Leeni: I'd be willing to bet it doesn't do that automatically for user-defined classes.

11:42 Leeni: you are right it doesn't

11:43 dnolen: Leeni: in anycase "large" slowdowns doesn't really play out much in practice. If you need to write high perf low allocation code in Clojure it can be done w/o much effort.

11:44 Arafangion: The JVM, can, at least, abstract most of the performance issues of using the native platform allocator.

11:44 dnolen: in any large code base you need to produce against mutability somewhere - so what are you going to do? deep copy an entire nested structure

11:44 yuck

11:45 expect const to save you?

11:45 yuck

11:45 expect that somebody would cast to a mutable type?

11:45 yuck

11:45 Arafangion: dnolen: Arguably. The need to do so depends on your application design.

11:45 There is still, however, a lot of copying going on. :(

11:46 dnolen: Arafangion: well I'm no expert but I've rarely written code that doesn't need it after certain threshold.

11:47 Leeni: here's the dealio, if most basic operation (walking through a sequence) is slow then it's gonna affect all programs...

11:47 Arafangion: dnolen: I tend to restrict such large structures to the module it belongs to.

11:47 Leeni: still need to solve the mistery of low CPU utilization

11:47 Arafangion: Leeni: Walking through a sequence is slow in python, too, despite python not needing to pass tails.

11:48 Leeni: that's weird

11:48 Arafangion: Leeni: Mostly because function calls are slow.

11:48 Leeni: I've wrote a java function that returns and Iterable like clojure function range and was much faster

11:49 then again, you couldn't pass it around

11:49 I mean mid-iteration

11:51 Arafangion: Leeni: I should get to bed, otherwise I"m going to stay up thinking of a nice implementation that would allow you to do that, it doesn't seem to be that hard a problem.

11:51 Again, speaking of someone who has never done clojure, perhaps there's something I'm missing entirely. :(

11:51 dnolen: Arafangion: it's hard, you need to consider concurrency, locks, etc.

11:52 Leeni: gotta figure out how to make the clojure 1.3 work with clojurebox or counterclockwise

11:52 Arafangion: dnolen: Oh, concurrency, forgot about that, but it'd still be doable, imho.

11:52 dnolen: Arafangion: of course Clojure has already done the work for you :) and it's hard.

11:53 Arafangion: dnolen: From what I hear, you're optimising for the worst case, specifically, the assumption that a tail is always passed.

11:53 dnolen: Arafangion: just working for an Iterable is not enough anyhow, you want array-like, set-like, etc.

11:53 map-like

11:53 Arafangion: Meh, that makes it a non-trivial amount of code!

11:54 dnolen: thus be lazy, use Clojure

11:54 work done

11:54 Arafangion: On that note, G'night. :)

11:54 Leeni: :D

11:56 dnolen, do you know why on this benchmark http://shootout.alioth.debian.org/u64q/benchmark.php?test=fannkuchredux&lang=all clojure's CPU utilization doesn't exceed 75% per core?

11:56 or any other benchmarks practically

11:56 Arafangion: Possibly locks.

11:57 Leeni: then C and java would have same problem too

11:57 these algorythms seem easily paralelizable without locks

11:58 dnolen: Leeni: no I haven't looked at that code very closely, but that's code based off of 1.2.0, and I see some things that I wouldn't do.

11:59 Leeni: under notes it says 1.3.0

11:59 dnolen: the code itself is written for 1.2.0

11:59 Leeni: quite probable

11:59 what wouldnt you do?

11:59 dnolen: Leeni: I know, I've been writing Clojure for 3 years :)

12:00 Leeni: well I haven't and I can't find the screwup

12:01 dnolen: remove all the unnecessary casting, don't use range to allocate contents of array.

12:01 Leeni: I was thinking pmap was enough to get all the cores running at max

12:02 hehe I use range a lot

12:02 or (iterate inc 0)

12:02 dnolen: Leeni: as you should, unless you writing silly benchmarks.

12:02 Leeni: yeah I know range is much slower than a nice loop recur

12:27 thorwil: i suspect that i have a case where i can't compile a file, because it refers to a class in a required file, in which it's the job of a macro to create that class

12:28 actually, if i require a file, all the macros should get expanded, before anything else happens, or?

12:31 it's appengine-magic's defentity, e.g.: (ds/defentity Article [title, body, created, updated])

12:31 where i need to refer to Article in another .clj

12:36 defentity expands to a defrecord: https://github.com/gcv/appengine-magic/blob/master/src/appengine_magic/services/datastore.clj#L380

12:42 gfredericks: thorwil: what sort of error are you getting?

12:43 and do you remember to import the class?

12:44 thorwil: Unable to resolve classname: Article

12:45 gfredericks: i take this needs special handling then. import apparently ;)

12:45 gfredericks: thorwil: anytime you use a class created with defrecord or deftype you have to import it to refer to it directly

12:48 thorwil: gfredericks: ah, thanks. given the defrecord is in tlog.models.backing and called Article, what's the right import?

12:49 * thorwil hoped it would be tlog.models.backing.Article

12:52 thorwil: nm, got things mixed up :)

12:56 halarnold2000: does stuart sierra have a nik on this channel?

12:57 gfredericks: thorwil: your hope looks right to me, which I presume you figured out on your own while I was not replying

12:58 thorwil: gfredericks: indeed

12:59 i was just juggling too many buffers ...

12:59 gfredericks: buffer-juggling => buggling

13:01 zerokarmaleft: buffuggling

13:02 gfredericks: (inc zerokarmaleft)

13:02 lazybot: ⟹ 1

13:02 gfredericks: HA! Whaddayagonna call yourself now!

13:03 thorwil: lol

13:11 halarnold2000: .

13:19 zerokarmaleft: gfredericks: i'm immutable :P

13:20 gfredericks: zerokarmaleft: does that ever change?

13:23 zerokarmaleft: gfredericks: probably when i get married and have kids

13:31 mbac: what's the way to represent an association list in clojure?

13:31 is a list of vectors appropriate?

13:32 ([a b] [x y])

13:32 duck1123: mbac, there's a hash: {a b x y}

13:33 do you want to be able to find b if you have a?

13:33 melipone: I need to use the expt function from clojure.contrib.math but the abs function is conflicting with Incanter.core. How do I mix the two?

13:33 Bronsa: melipone: :as ?

13:34 bsod1: is there a better way to reload definitions other than calling (load-file ...) again?

13:34 melipone: okay, that might work. I was trying (use 'incanter.core :exclude abs) but that didn't work

13:35 Bronsa: melipone: try with :exclude [abs]

13:35 mbac: i only want to iterate them. hashes seem overkill

13:35 duck1123: melipone: usually it's better to either require with a prefix (:as) or use only the vars you need (:only)

13:35 melipone: thanks!

13:36 gfredericks: mbac: hashes are probably more idiomatic. And they're easy to iterate over because they're seqable: ##(seq {:a 3 :b 489 :c 28})

13:36 lazybot: ⇒ ([:a 3] [:b 489] [:c 28])

13:37 gfredericks: but if you have some tiny piece of code where you feel like it's silly to use a hash, then I don't think anybody will jump out from behind a bush and yell at you

13:37 mbac: haha

13:38 duck1123: it all really depends on what you want to do with them. A seq of vectors might be more appropriate for you

13:38 gfredericks: mbac: hard to say anything else without more details

13:38 mbac: that's about it.

13:40 * devn jumps out from behind a bush

13:41 * devn points his finger at mbac

13:41 devn: how DARE YOU, sir!

13:42 mbac: what's the function that takes an f and a coll and returns the first x where f x is true

13:42 (coll means sequence-like thing right?)

13:42 zerokarmaleft: some

13:44 mbac: close, i want the x not the truthness

13:44 Bronsa: mbac: (comp first filter)

13:44 eanxgeek: ping #clojure anyone here by chance familar with selenium? trying to lein compile some code java.io.FileNotFoundException: Could not locate selenium__init.class and I'm trying to figure out where that would come from.

13:44 Bronsa: ,((comp first filter) odd? [0 2 4 1 2])

13:44 duck1123: ,(some even? [1 2 3 4])

13:44 clojurebot: true

13:44 1

13:45 zerokarmaleft: Bronsa's then

13:45 mbac: i only want the first one :)

13:46 duck1123: Bronsa was right

13:46 mbac: and only want to compute all but the first

13:46 that seems wordy

13:46 Bronsa: wait, what

13:46 mbac: er, wait

13:46 and only want to compute the first

13:46 duck1123: ,(->> [1 2 3 4] (filter odd?) first)

13:46 clojurebot: 1

13:47 zerokarmaleft: you have to compute on the things that come before it necessarily

13:47 mbac: sure

13:47 Bronsa: mbac: then being filter lazy, it will compute until one is true

13:47 zerokarmaleft: it's lazy though, it stops after the first

13:47 Bronsa: and returd that

13:47 *return

13:48 simply (def ffilter (comp first filter))

13:48 and have fun

13:49 * devn thinks it's a mistake to not include clojure.repl (specifically the doc and source macros) in core

13:50 Bronsa: why?

13:50 clojurebot: why not?

13:50 devn: because i think it will slow down newcomers

13:51 mbac: whoa, magic ->> thing

13:51 Bronsa: mbac: -> too

13:51 devn: Maybe I'm overstating it, but im working on a tutorial for a meetup group I run and I think the extra step of requiring clojure.repl in all of your projects in order to get (doc) and (source) is annoying

13:52 duck1123: those 2 forms are great for turning big complicated fns into simple lists

13:52 Bronsa: devn: personally i use doc and source only from a repl

13:52 which is the usecase for them in some code?

13:52 devn: Bronsa: coincidentally, i only develop when I'm using...a repl

13:53 mbac: are lists always lazy?

13:53 devn: Bronsa: I see where you're coming from, but I miss the old days of not needing to (use 'clojure.repl) every single time I start a repl

13:54 Bronsa: devn: oh

13:54 devn: it's just extra garbage that new people to the language should not need to do.

13:54 Bronsa: i always start my repl with lein repl

13:54 and it uses clojure.repl by default

13:54 i tought it was the repl, not lein

13:54 devn: Bronsa: so...that's one way out of how many to start a repl?

13:54 Bronsa: didn't mean to say that

13:54 i tought that when starting the repl clojure.repl was automatically :used

13:55 didnt notice it was lein

13:55 devn: *nod* -- this is a change as of 1.3 I believe

13:55 fliebel: Are there any other binary libs for clojure other than Gloss?

13:56 mbac: oh filter does the lazy

13:57 chewbranca: is there a form of flatten that allows you to specify depth or type? I've got a list of lists of vectors, and I want to flatten that to be a single list of vectors

13:57 Bronsa: mbac: most of the core seq fns returns lazy seqs

13:57 chewbranca: and flatten will flatten the vectors down as well

13:58 Bronsa: s/ns/n/

13:58 lazybot: <Bronsa> mbac: most of the core seq fn return lazy seqs

13:58 ibdknox: the ones that can will do so :)

13:59 gfredericks: is there an example of a function that returns a seq that is not lazy?

13:59 chewbranca: gogo internet: http://stackoverflow.com/questions/5232350/clojure-semi-flattening-a-nested-sequence

13:59 ibdknox: ,(doc reverse)

14:00 clojurebot: "([coll]); Returns a seq of the items in coll in reverse order. Not lazy."

14:00 ibdknox: :)

14:00 gfredericks: ibdknox: that was certainly easy. :)

14:03 duck1123: ,(doc doall)

14:03 clojurebot: "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. doall can be used to force any effects. Walks through the successive nexts of the seq, retains the head and returns it, thus causing the entire seq to reside in memory at one time."

14:04 gfredericks: obvious exception

14:04 sritchie: ibdknox, do you have any examples of how to use sandbar for authentication with noir?

14:05 specifically, I'm not sure how to to use server/add-middleware to do something like this: https://github.com/brentonashworth/sandbar/blob/master/src/examples/auth/auth.clj#L130

14:06 ibdknox: sritchie: I haven't used it, because it didn't seem to provide anything I needed, to do that, though you just need to add those two middleware separately

14:07 sritchie: you won't need wrap-file :)

14:07 sritchie: you could also comp them

14:07 sritchie: got it, so just add (server/add-middleware with-security authorize) in there

14:07 ibdknox: yep

14:08 sritchie: nice, that tossed a few hours, but I'll figure it out from the sandbar side

14:08 s/hours/errors

14:08 lazybot: <sritchie> nice, that tossed a few errors, but I'll figure it out from the sandbar side

14:08 sritchie: Key must be integer, etc :)

14:08 ibdknox: I think you'll need to include his session middleware too, which I'm not sure how way that'll play with mine

14:09 in theory they shouldn't mess with eachother

14:09 but I've not tried it

14:10 sritchie: yeah, you're right, that worked out fine

14:12 so, all I'm looking to do is restrict access to certain pages based on roles -- in noir, I could do the same thing by examining noir's session, right?

14:12 mbac: can i have fold?

14:12 reduce isn't cutting it for me

14:14 dnolen: foldl foldr considered slightly harmful, http://docs.google.com/viewer?url=http://research.sun.com/projects/plrg/Publications/ICFPAugust2009Steele.pdf&pli=1

14:14 ibdknox: sritchie: yeah, it's probably a bit simpler. You would use a pre-route, then check if the person has access, if not, redirect to login or whatever :)

14:15 sritchie: for example: https://github.com/ibdknox/Noir-blog/blob/master/src/noir_blog/views/admin.clj#L50

14:15 mbac: dnolen, i know. i want it anyway.

14:15 dnolen: mbac: can't help you there :)

14:16 sritchie: ibdknox: got it, that's great

14:16 dnolen: and if rhickey #strangeloop talk is any indicator, it's not going to happen. mayhaps as a contrib thing, but I don't hear many people asking for it.

14:18 mbac: well, what's better then? i want to update state as i consume a list

14:20 dnolen: mbac: so why not reduce + an atom?

14:20 mbac: hmm?

14:27 there's seriously no fold function because it's not inherently parallelizable? this is better than having thousands of people try write their own buggy versions?

14:27 s/try write/try to write/

14:27 lazybot: <mbac> there's seriously no fold function because it's not inherently parallelizable? this is better than having thousands of people try to write their own buggy versions?

14:28 dnolen: mbac: thousands? if you feel so strongly about it bring it up on the mailing list, dev list.

14:28 mbac: thousands of crappy implementations, at least

14:29 i know mine will be

14:29 dnolen: mbac: I have yet see any implementations of it at all.

14:29 much less thousands.

14:31 mbac: i'm projecting into the future a little

14:32 dnolen: people have been using Clojure for a while now, future hasn't arrived.

14:32 but honestly, sounds like something that could find a home in contrib.

14:34 and other people that want it can benefit from a good implementation. same thing w/ pattern matching - rhickey doesn't like that either.

14:34 dsantiago: dnolen, has he said why he doesn't like pattern matching?

14:34 dnolen: gotta run

14:35 mbac: http://pastebin.com/yAS3Fjhe there, i fixed clojure :)

14:36 gfredericks: mbac: don't you gotta have a 2-arg version?

14:37 mbac: see? i told you it'd be crappy

14:37 fliebel: dsantiago: From what I remember he just didn't like the current implementations.

14:37 dsantiago: Ah.

14:37 gfredericks: mbac: yeah, no motivation to prove your own point there :P

14:42 Leeni: isn't fold like reduce?

14:42 mbac: no

14:42 i mean, yes

14:43 but if you use a language which discourages mutation, fold is what all of the kids who miss for loops will want

14:43 except they don't know they want it, yet

14:44 gfredericks: foldl === reduce?

14:44 fliebel: behold the treeduce https://gist.github.com/951553

14:45 mbac: it's not. part of the power of fold is the accumulator isn't necessarily the same type as the elements in the collection

14:46 gfredericks: mbac: well clojure.core/reduce certainly doesn't enforce that. I use it assymetrically all the time.

14:46 fliebel: mbac: Does reduce require that?

14:48 mbac: int total=0; for(int i=0;i<a.length;i++) total+=a[i].length; best functional programmingifies to (foldl (fn [acc x] (length x)) 0 a)

14:49 gfredericks: (reduce + (map count a))?

14:49 I don't even see where the + happens in your version

14:49 mbac: yeah, i forgot

14:49 gfredericks: ah I see where it would go

14:49 mbac: (foldl (fn [acc x] (+ acc (length x))) 0 a)

14:50 gfredericks: so you're arguing that because something fits the imperative paradigm better, we ought to have it?

14:52 mbac: no, i'm arguing the loops that you use to get stuff done are strange

14:52 fold explicitly considers the start case

14:53 your reduce would have a bug if 0-arity + didn't rescue you

14:54 Leeni: reduce can take start value

14:54 mbac: i agree, you can not write bugs

14:54 ;)

14:54 Leeni: it also enables you to accumulate different type than that is the collection

14:55 gfredericks: mbac: so you consider fold to be a function that requires a start value?

14:55 Raynes: reduce lets you do anything you want.

14:55 gfredericks: ,(reduce conj [] #{7 8 4})

14:55 clojurebot: [4 7 8]

14:56 gfredericks: ^ different accumulated type

14:57 mbac: gfredericks, sort of

14:58 Leeni: I never know when to use reduce and when to use something like apply vec

14:58 mbac: fold has a well known form. with reduce i have to look closer

14:58 gfredericks: ,(doc vec)

14:58 clojurebot: "([coll]); Creates a new vector containing the contents of coll."

14:58 gfredericks: Leeni: apply vec sounds pretty useless; and apply vector is equivalent to vec

14:59 Leeni: yeah that

14:59 I mean I can often do a lot of stuff just with map and reduce

14:59 gfredericks: Leeni: reduce is a lot more general

14:59 Leeni: but maybe using specialised function is better

14:59 mbac: yes, that's it! reduce is too general. it's terrible

14:59 gfredericks: if all you're doing is trying to make a vector out of something, then you should prefer vec/vector

14:59 Leeni: perhaps faster

14:59 gfredericks: mbac: I don't mean it's any more general than fold

15:00 mbac: :)

15:00 gfredericks: in fact part of what makes this discussion hazy is that there's not a clear line between the two

15:00 mbac: there's a very clear line. fold has an explicit required start case

15:01 if you use it wrong the system stops you from having a bug

15:01 gfredericks: mbac: if we like the system to tell us when we have bugs we may as well use static types

15:01 mbac: hahah

15:01 i guess i should stick to ocaml

15:02 gfredericks: clojure's got flexibility all over the place

15:02 mbac: i know, it's horrible

15:02 gfredericks: then don't use clojure. apparently you don't like it.

15:02 mbac: i don't know how to do anything

15:03 Leeni: hey, anyone got clojurebox or counterclockwise to run with clojure 1.3?

15:03 gfredericks: btw, wikipedia doesn't agree with your strict definitions: http://en.wikipedia.org/wiki/Fold_(higher-order_function)

15:03 mbac: I think most of the people that use clojure appreciate the flexibility

15:04 I think that can be a personality thing though. Some people like it, some people don't.

15:04 mbac: i've noticed that

15:04 toxmeister: leeni: CCW 0.4 works fine w/ 1.3

15:04 gfredericks: I have a friend who would be great with clojure except for that one point, so he uses scala

15:04 mbac: it's not inherently bad, it's simply thwarting my expectations

15:06 gfredericks: mbac: what other languages do you use/like?

15:09 Leeni: toxmeister: my CCW feezes my eclipse when I try to connect to 1.3 REPL

15:21 mbac: gfredericks, besides ocaml? i guess C

15:21 python, when i'm doing project euler problems

15:23 gfredericks: do you find clojure more flexible/surprising than python?

15:23 mbac: no, they're a lot alike

15:23 philosophically, it seems

15:24 using python in a large codebase with multiple people drives me nuts though

15:25 gfredericks: I think immutable data and preferring pure functions can help keep down the chaos

15:25 mbac: agreed

15:27 gfredericks: mbac: I sympathize with you some. the dynamic types and stuff are definitely the part of clojure I'm least sure about

15:27 my personal approach is to use testing

15:28 my hunch is that could be better than a static language, because you're forced to write lots of tests, which give you confidence not only that you got all the types right, but that the program also does what you want it to

15:28 Leeni: what's the difference between deftype and defrecord?

15:30 gfredericks: defrecord gets you a map-compatible data structure. deftype is bare, and can even give you mutable fields if you need them

15:33 mabes: mbac: another version of foldl for you: https://github.com/amalloy/amalloy-utils/blob/master/src/amalloy/utils.clj#L72-74

15:33 in this case he aliased reduce to be foldl.. which wouldn't get the strict enforcement that you want

15:34 gfredericks: pretty easy to get it though: (def foldl #(reduce %1 %2 %3))

15:34 mabes: yeah

15:35 gfredericks: I wonder if reverse on vectors is fast

15:35 mabes: ,(doc reverse)

15:36 clojurebot: "([coll]); Returns a seq of the items in coll in reverse order. Not lazy."

15:36 mbac: gfredericks, disciplined coding, almost universally, doesn't work

15:36 gfredericks: mbac: did I say otherwise?

15:36 mbac: i don't think so

15:36 gfredericks: mbac: what does work?

15:36 mbac: i'm paving the way for why i'd never write unit tests

15:36 gfredericks: oh I see

15:37 mbac: the language should make it impossible to push a bad solution

15:37 gfredericks: oh golly.

15:37 mabes: mbac: do you use ocaml professionally?

15:37 mbac: yeah

15:38 gfredericks: mbac: if the language doesn't let you write incorrect code, I don't think it could be a programming language

15:38 mbac: no doubt

15:38 gfredericks: so I guess your statement hinges on what you mean by "bad solution"

15:38 mbac: there's an interesting proof in there somewhere :)

15:38 gfredericks: easy:

15:38 Requirements: push a bad solution

15:39 mabes: after reading "Ocam for the Masses" and a few tutorials I must say that I am intrigued.. I've never used a language with a decent type system but the benefits sound nice

15:39 mbac: ideally your developers write unit tests and check their mallocs and do proper mutex locking blah blah

15:39 mabes: s/Ocam/Ocaml/

15:39 lazybot: <mabes> after reading "Ocaml for the Masses" and a few tutorials I must say that I am intrigued.. I've never used a language with a decent type system but the benefits sound nice

15:40 mabes: (here is the link to the mentioned article: http://queue.acm.org/detail.cfm?id=2038036)

15:40 mbac: but if they're human beings they're going to forego all that shit if it means they get it out the door faster

15:40 mabes: mbac: what industry do you work in?

15:41 mbac: mabes, my boss wrote that article

15:41 mabes: mbac: awesome! I've been watching some of his presentations too :)

15:42 aside from HFT OCaml hasn't really seen much in roads in industry it would seem

15:45 mbac: what is your opinion on clojure's approach to concurrency and state?

15:46 mbac: what's clojure's approach?

15:46 mabes: :)

15:46 http://clojure.org/state

15:47 gfredericks: piles and piles of mutexes

15:47 mabes: http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey

15:48 gfredericks: under the hood I suppose so, but the overall premise is to remove that complexity from the programmer, right?

15:48 gfredericks: mabes: yeah, I was kidding. it wasn't very funny.

15:48 mabes: gfredericks: lol.. okay

15:48 gfredericks: sometimes I forget whether jokes are supposed to be funny or not.

15:49 Leeni: btw about reduce

15:49 it does have one weird behaviour

15:49 mabes: gfredericks: sarcasm can also be lost over IRC as well ;)

15:49 Leeni: if you hand it an empty sequence it will invoke the function with no arguments

15:49 gfredericks: mabes: I can get it lost face-to-face if I try hard enough.

15:50 mbac: everything on irc is sarcastic, unless explicitly noted otherwise

15:50 Leeni: if you hand it a 2 or more elements it will do a reduce

15:50 gfredericks: Leeni: not much else for it to do, right?

15:50 Leeni: and if you hand it sequence of one element it will just return the element

15:50 that's the weird one

15:50 gfredericks: :/

15:51 Leeni: in all other cases function gets called at least once

15:51 mbac: (defalias foldl reduce)

15:51 lulz

15:51 Leeni: except when sequence has 1 element

15:51 then the function doesn't get called

15:52 gfredericks: Leeni: I think it makes sense, unless you phrase it specifically so as to make it sound like it doesn't make sense :P would you do it differently?

15:52 Leeni: perhaps invoke the function with one argument?

15:52 gfredericks: I think that's even weirder

15:53 really the exceptional case is the 0-arg case

15:54 I think if you're going to call fold/reduce, you've got three options: 1), never call it on an empty list, 2) give an initial value that will be returned if you use an empty list, 3) barring the first two, give a reduce function that will accept 0 args

15:54 case 3 is what you get for rejecting 1 and 2

15:54 I think the only other sane thing is to throw an error in case 3

15:54 mabes: mbac: have any book recommendations (or other resources) for learning ocaml? From what I've googled, "Introduction to Objective Caml" seems to be well liked: http://caml.inria.fr/cgi-bin/hump.en.cgi?contrib=347

15:56 mbac: that's the best ocaml book available

15:56 which is to say it sucks the least

15:57 mabes: of course

16:03 mbac: have any book recommendations for learning clojure? :)

16:06 zerokarmaleft: mbac: i enjoyed JoC

16:06 mabes: mbac: given your background I think you would like Joy Of Clojure

16:08 mbac: sounds like the winner

16:09 mabes: which is to say you will hate the book the least

16:09 mbac: haha

16:13 ghiu: hi, i'm using intellij idea and leiningen. how can i access the jars imported in the /lib dir of the project from the build-in repl of my die? it seems to have a class path that is different from the one used by lein and the project. thanks

16:16 oh, found it

16:16 i had to add the lib path to the "dependancies" modules in the project settings

16:21 gfredericks: is it possible to override the clojure reader?

16:26 duck1123: gfredericks: if you're asking like reader macros, no

16:34 gfredericks: duck1123: I was thinking like (binding [clojure.core/read my-silly-reader-fn] (require ...))

16:34 it's a stupid idea anyhow. Was just curious if that would work.

16:35 mbac: does this form (let [foo 1 foo (+ foo 1)] foo) particularly infuriate anyone?

16:36 gfredericks: mbac: it's a great way to imitate imperative programming! :)

16:37 Bronsa: s/imperative/procedural/ right?

16:37 mbac: i don't want to risk re-using the old value by mistake

16:37 so... shadow it!

16:37 gfredericks: I think it certainly has the danger to screw up readability. Sometimes I can't resist using it for getting an argument into a canonical form though. I think clojure.core does that as well.

16:37 Bronsa: dunno, what's the difference?

16:37 mbac: of course then you risk much more subtle scoping bugs

16:38 gfredericks: mbac: I wouldn't go out of your way to hide things like that. If you want isolation, create a separate function to call.

16:39 Bronsa: gfredericks: as per wikipedia procedural can be used as a synonym for imperative

16:39 so i think i am wrong

16:39 gfredericks: Bronsa: nah, you _were_ wrong. Now you're right!

16:39 probably.

16:39 Bronsa: gfredericks: lol right

17:04 michaelr525: hello!

17:06 gfredericks: michaelr525: hello!

17:20 bdb_: I'm having some trouble getting swank-clojure to work with lein: I've installed the plugin & ~/.lein/bin/ is on my path, but `lein swank` still says "That's not a task."

17:21 where should I look next to debug this?

17:21 $ which swank-clojure

17:21 $ lein swank

17:21 That's not a task. Use "lein help" to list all tasks.

17:22 hmm, that didn't render right in my irc client: `which` returns: /Users/brandon/.lein/bin/swank-clojure

17:27 duck1123: bdb_: is your lein up to date?

17:28 bdb_: yup: leiLeiningen 1.6.1.1 on Java 1.6.0_26 Java HotSpot(TM) 64-Bit Server VM

17:29 ibdknox: bdb_: ls ~/.lein/plugins

17:29 is swank actually in there?

17:29 bsod1: wow, I got NullPointerException in Clojure!

17:29 bdb_: yup

17:29 gfredericks: bsod1: ##(nil :foo)

17:29 lazybot: java.lang.IllegalArgumentException: Can't call nil

17:29 gfredericks: dangit

17:29 I know there's an easy way to do it...

17:29 bdb_: aaaahh two versions were in there

17:30 i ran uninstall on the older version

17:30 ibdknox: :)

17:30 duck1123: ##(.getFoo nil)

17:30 bdb_: and `lein help` shows swank now!

17:30 lazybot: java.lang.NullPointerException

17:30 gfredericks: (map nil [1])

17:30 ,(map nil [1])

17:30 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.NullPointerException>

17:30 bsod1: heh

17:31 gfredericks: bsod1: would you prefer clojure defined a NilPointerException? :)

17:31 bdb_: thanks idbknox

17:31 ibdknox: bdb_: leave it to a VIM user to save the day ;)

17:31 bdb_: heh -- I'm a vim guy myself

17:32 ibdknox: haha

17:32 bsod1: ,(* 1 nil)

17:32 clojurebot: #<NullPointerException java.lang.NullPointerException>

17:32 bdb_: been writing clojure in vim for a couple weeks and been using a little macro plus tmux to send forms to the repl

17:32 and decided it was finally time to bite the bullet and learn some emacs

17:32 ibdknox: vimclojure would make that much nicer for you

17:33 bdb_: yeah, was using that in offline mode

17:35 Bronsa: ,()

17:35 clojurebot: ()

17:35 Bronsa: ,(nil)

17:35 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Can't call nil, compiling:(NO_SOURCE_PATH:0)>

17:36 gtrak``: ,(println "Clojure is awesome")

17:36 clojurebot: Clojure is awesome

17:37 gfredericks: ,(println "&(println \"clojurebot is awesome\")")

17:37 clojurebot: &(println "clojurebot is awesome")

17:37 lazybot: ⇒ clojurebot is awesome nil

17:37 Bronsa: lol

17:37 bdb_: so tempting to write an infinite bot loop :-P

17:38 gfredericks: bdb_: lazybot's arrow prevents it

17:38 ibdknox: guarded against

17:38 raek: bdb_: this is why lazybot's output is prefixed with ⇒

17:38 bdb_: ah, nice

17:38 gfredericks: somebody else say it too!

17:38 gtrak``: nerds :-)

17:38 Bronsa: it's not nice

17:38 it ruins fun

17:54 sritchie: you'd just need one more bot that responds to the arrow, I think

18:14 Leeni: man I can't get swank to work with clojure 1.3

18:14 it just crashes

18:18 Raynes: technomancy: Ping.

18:20 lnostdal_: works fine here

18:23 Leeni: changed clojure jar version to 1.3 in lein.bat and now leinigen crashes

18:24 duck1123: Leeni: update lein, remove all older versions of swank and install an up to date version

18:24 raek: Leeni: change the version in your project.clj file, not in leiningen's internals

18:24 Leeni: raek I did that and it crashed on lein swank

18:25 raek: leiningen uses two processes: one for build tool stuff and one for your code

18:25 which version of swank-clojure?

18:25 Leeni: yes but it ran swank with same version as build tool stuff

18:25 1.3.3

18:25 raek: do you have one as a dev-dependency? do you have one installed as a plugin?

18:25 Leeni: yes

18:25 both

18:25 raek: make sure you don't have both

18:26 if they are different versions, strange things happens

18:26 Leeni: they are both the same version

18:26 raek: prefer using it as a plugin

18:27 Leeni: I downloaded newest version of everything, put clojure 1.3 and swank 1.3.3 in project.clj, ran lein install plugin for swank 1.3.3

18:27 then lein swank in project folder crashed

18:28 raek: stacktrace?

18:28 Leeni: Caused by: java.lang.RuntimeException: Unable to resolve symbol: print-doc in th is context

18:29 then I changed .lein/bin/swank-clojure.bat so it pointed to 1.3 clojure instead 1.2 and nothing changed

18:29 now I changed version used in lein.bat to 1.3 and I get a different error

18:30 Exception in thread "main" java.lang.IllegalStateException: Can't dynamically bi nd non-dynamic var: leiningen.compile/*silently*

18:30 duck1123: I don't know what version other people are using, but I've been using 1.4.0-SNAPSHOT with no problems

18:30 Leeni: so apparently lein swank runs swank with whatever version of clojure it uses for itself

18:30 which was 1.2, now I changed that to 1.3 and now lein doesn't work

18:30 raek: Leeni: leiningen uses clojure 1.2 for its own process, but that shouldn't interfere with you using clojure 1.3 in your project

18:31 as I said, lein uses two processes

18:31 Leeni: well apparently there's no way to tell it to run swank with 1.3

18:31 raek: swank runs in your project process

18:31 duck1123: and swank should use the project's version

18:31 raek: which uses the clojure version you choose

18:32 Leeni: I must be crazy then

18:32 changed lein version back to 1.2

18:33 raek: Leeni: if you run "lein repl", you should get a 1.3 repl

18:33 Leeni: and I get this error when running lein swank

18:33 http://pastebin.com/YTQ8GxsX

18:33 raek: Leeni: when you get swank to work, it will run in that classpath

18:34 Leeni: well that's the problem, it clearly doesn't

18:34 raek: Leeni: maybe clojure 1.3 isn't supported in the stable version of swank-clojure yes. have you tried 1.4.0-SNAPSHOT?

18:34 *yet

18:35 after all, clojure 1.3 was released fairly recently

18:36 duck1123: raek: I'm pretty sure it worked in swank 1.3.0. The important thing is that he has only 1 version of swank

18:37 Leeni: delete all your swank plugins, remove it as a dev dependency, delete lib/ and classes, then install 1.4.0-SNAPSHOT as a plugin

18:37 bdb_: Is there a naming convention for functions which return a mutated object? "set-foo" just doesn't seem right, since it's not actually changing it's argument… but I guess that would be "set-foo!" right? -- what's the convention?

18:37 Leeni: duck then how will I run swank with my project in classpath?

18:38 duck1123: lein swank, just as normal

18:38 raek: bdb_: the ! sign is for functions whose side-effects are not safe in transactions

18:38 bdb_: fair enough, so here's an example:

18:38 raek: for example, if you 'swap!' an atom in a transaction, and that transaction is retried, the 'swap!' still happened and is not "rolled back"

18:39 bdb_: yup, gotcha

18:39 let's say I have some immutable hash representing a person

18:39 raek: Leeni: do you have additional dependencies? sometime a dependency pulls in an old version of swank-clojure...

18:40 bdb_: with :first-name and :last-name keys

18:40 and i want to provide set-name which splits on " " and returns a new person object w/ the first and last names set (yes, i know this is not a real example… you wouldn't every assume people have exactly one space and two names)

18:40 what do you call that function?

18:40 set-name ?

18:40 with-name ?

18:40 Leeni: raek:seems to be the case

18:41 bdb_: name= ?

18:41 raek: I like with-name

18:42 bdb_: so i like that too and with-meta from the std lib seems to say that's a good idea… but i also see the with- prefix for functions which affect lexical bindings, like with-out-str, etc

18:42 raek: I think that's how Joda-time names their methods

18:42 yeah, I see the conflict...

18:43 well, I don't know. names are always hard...

18:43 Leeni: hm how do I figure out last release on github

18:43 raek: Leeni: is the dependency incanter?

18:43 bdb_: yeah, hence I'm asking for help :-) names are the hardest thing haha

18:44 amalloy: bdb_: fwiw, with- is mostly for things that affect dynamic scope, not lexical scope. with-out-str is an example of that

18:44 bdb_: d'oh yeah, dynamic scope is what i meant

18:44 raek: Leeni: now you have experience the reason why you should use swank-clojure as a plugin and not as a dev-dep... :-)

18:44 Leeni: trying to figure out last Enlive version

18:45 well yeah but how do I run it as plugin and will it still let me use my project's classpath

18:45 duck1123: Leeni: Network view is always good to see which braches belong where

18:45 Leeni: I think other dev deps will always pull their versions

18:45 so how to avoid that

18:45 duck1123: exclusions

18:46 you can specify that a dependency should exclude other dependencies

18:46 raek: Leeni: if you have it as a plugin, it behaves like an invisible :dev-depenencies entry in your project.clj

18:47 well, in all your project.clj files

18:47 duck1123: You can also exclude globally. I recommend that people using 1.3 put a global exclusion on the older contrib libraries

18:47 raek: duck1123: oh, where do you set that global setting?

18:48 duck1123: :exclusions key (ex. https://github.com/duck1123/jiksnu/blob/master/project.clj#L44)

18:49 FrankL: what's the easiest way to call new clojure code from an existing java project in eclipse?

18:49 i have ccw installed

18:50 Leeni: thanks

18:50 I got it to run

18:50 successfuly connected from clojurebosx

18:50 duck1123: FrankL: If you use :gen-class in the clojure project, you can create a real Class that you can treat just like a Java class

18:51 FrankL: duck: yup, that's exactly what i want to do

18:51 Leeni: I'll have to look into exclusions if I wanna get my old projects to run

18:52 FrankL: but the old project doesn't 'see' the class specified in clojure

18:52 although i added the new project as a requirement

18:53 duck1123: I wonder if that has something to do with eclipse. So these are two separate projects?

18:54 raek: FrankL: https://gist.github.com/1273014

18:54 duck1123: Clojure has to be told to compile those namespaces into classes, I wonder if something about that isn't getting done when eclipse traces the dependencies

18:55 raek: FrankL: a pretty simple way is to skip gen-class and use clojure.lang.RT to access the clojure stuff

18:55 might not be the fastest way if you make a lot of java->clojure calls

18:55 hrm, well, it shouldn't be that slow, actually

18:56 FrankL: for this to work you need the clojure source and the clojure jars on the classpath

18:56 FrankL: thanks duck & raek, i'm looking at both options

18:57 raek: I think the simplest way is to make a new lein project, run lein deps and then add src/ and the jars in lib/* to your eclipse project classpath

18:58 Leeni: still can't get CCW to connect to repl though

18:58 eclipse just freezes

18:58 raek: if CCW has some lein integration, disregard my instructions for that part and follow the official docs :)

19:00 Leeni: when I click Connect to REPL in eclipse should I be connecting to the port "lein repl" gives or the swank server?

19:03 duck1123: ccw uses repl, not swank

19:05 wink: afaik it does not work with "lein repl", it's another repl

19:06 duck1123: it works with nrepl

19:13 FrankL: yay, got it to work

19:13 had to compile the .clj file from the repl myself

19:13 and then i could just use the class methods from a different project

19:13 thanks again duck & raek

19:14 duck1123: congrats. Gen-class is good when you don't even want to think about the fact that it's clojure from the java side

19:15 like when you're implementing some plugin interface

19:15 FrankL: exactly

19:36 bdb_: I'm sure this function is in core, but I can't find it: How do I get some value from a hash, apply a function to it, and return a new hash with that key/value pair replaced?

19:36 amalloy: &(doc update-in)

19:36 lazybot: ⇒ "([m [k & ks] f & args]); 'Updates' a value in a nested associative structure, where ks is a sequence of keys and f is a function that will take the old value and any supplied args and return the new value, and returns a new nested structure. If any levels do not exist, hash-maps will be created."

19:36 bdb_: awesome. thanks!

19:37 amalloy: bdb_: it probably wouldn't help in this case, but often if there's something you think is in core but don't know what to call it, lazybot can help

19:37 $findfn {:a 1} :b 2 {:a 1 :b 2}

19:37 lazybot: [clojure.core/assoc]

19:37 bdb_: cmd+f in my browser only goes so far :-)

20:05 duck1123: there's also clojureatlas.com for when you have an idea what you want, but not what it's called

20:16 bdb_: duck: ok that's pretty damn cool :-)

20:17 amalloy: aw, no "pretty damn cool" for lazybot?

20:17 gfredericks: duck1123: let's be honest: are those fibonacci numbers?

20:18 (inc lazybot)

20:18 lazybot: ⟹ -1

20:18 bdb_: heh, they are both pretty damn cool

20:18 gfredericks: (inc clojureatlas.com)

20:18 lazybot: ⟹ 1

20:18 duck1123: gfredericks: yes they are

20:18 amalloy: hahahaha poor lazybot. gets dec'd when he makes a mistake, and so rarely inc'd

20:18 but you don't mind, do you??

20:18 lazybot: amalloy: Uh, no. Why would you even ask?

20:19 gfredericks: amalloy: it's just too much fun to resist using lazybot to dec lazybot.

20:19 bdb_: (inc lazybot) ; just for you amalloy

20:19 aw, no comment support :-P

20:19 (inc lazybot)

20:19 lazybot: ⟹ 0

20:19 amalloy: yeah, inc is dumb

20:19 gfredericks: (dec lazybot)

20:19 lazybot: ⟹ -1

20:19 bdb_: haha

20:19 gfredericks: ^ cause of no comment support

20:19 wanted to put that as a comment, but no...

20:19 amalloy: nice. fair point

20:20 gfredericks: (* 3 lazybot)

20:20 amalloy: i guess it wouldn't be hard to add that, actually, but it hardly seems worth the bother

20:21 gfredericks: amalloy: I'm on it

20:25 wtf. I spent 2 minutes agonizing over that regex and github just discarded the change.

20:26 (dec github.com)

20:26 lazybot: ⟹ -1

20:27 gfredericks: I think github got confused since I had forked sexpbot way back in the day and it's since been renamed and reowned.

20:31 amalloy: interesting

20:31 we do try to maximize your inconvenience

20:32 gfredericks: now you know how badly I wanted to create that pull request.

20:33 amalloy: and instead you created it badly?

20:34 gfredericks: amalloy: the grammar?

20:34 or the code?

20:34 amalloy: no, just that you tried to send it and github failed you

20:35 gfredericks: oh I think this has been a wordplay.

20:36 amalloy: (inc gfredericks) ; thanks for pull request

20:36 lazybot: ⟹ 2

20:36 gfredericks: now my evening is complete

20:37 * gfredericks didn't realize immediately that amalloy was cleverly demonstrating the new feature as well

20:37 bdb_: Sweet! I'm going to give myself credit for supporting the clojure community w/ my awesome inadvertent feature request

20:38 duck1123: (inc bdb_) ; you've inadvertently helped us all

20:38 lazybot: ⟹ 1

20:38 gfredericks: amalloy: I thought about converting it to use (read-string) instead of just the regexing

20:39 in other words I overthought it.

20:39 amalloy: gfredericks: meh. the goal was for it to be fast, since it's checked every time he sees a message from anyone in any channel

20:40 gfredericks: ah ha

20:40 wouldn't want to stress him out

20:40 amalloy: not that we're short on CPU time on the server, but just as a matter of good practice

20:40 bdb_: Oh hey, I've indirectly helped too: I'm brandonbloom -- thanks for pulling my fixes to the links in the lazybot read me

20:40 gfredericks: of course

20:40 bdb_: i mean directly*

20:41 *sigh* i suck at typing/speaking/etc :-P

20:44 gfredericks: man now every time I say anything I'm going to imagine poor lazybot churning it through that regex...

20:45 amalloy: gfredericks: #"^\(" is going to mean he short-circuits pretty fast :P

20:46 gfredericks: the world is merciful after all

20:46 (sometimes)

21:17 duck1123: Does anyone know which namespace has a *debug* var? this dynamic warning is driving me nuts

21:19 I really wish the dynamic warnings had shown the fully-qualified vars

21:22 amalloy: yuck. no qualified name, no filename, no compiler stacktrace? that's tough to fix

21:23 gfredericks: unzip lib/* and grep?

21:23 duck1123: just found it. Yay! one less warning

21:24 amalloy: gfredericks: well, it could be compiled. you might have to search for _STAR_debug_STAR_

21:25 duck1123: who was the offender?

21:26 duck1123: It was in lamina. I've been maintaining a branch with all the changes to work in 1.3, but I guess I missed one

21:26 I'm updating all of the dependencies, trying to get rid of the last warnings

21:28 does anyone know how long it will be before a build of algo.generic is up on the sonatype repo?

21:32 icefox: Should Clojure documentation end in a period?

21:38 Poking around in jira I didn't see anything, does Clojure have something like the Linux Janitor tasks?

22:28 zakwilson: Congomongo converts string keys to keywords. I do not want this behavior in some cases. Can I turn it off?

22:37 Never mind. Found it - coerce/*keywordize*

22:43 amalloy: zakwilson: oh really? i wish i had known that

22:43 zakwilson: amalloy: well, documentation is a bit lacking, so I had to RTFS. Didn't take too long to find though.

22:44 It's kind of important too since I'm storing a bunch of maps with string keys and doing compute-intensive things with them. Keyword comparisons are much slower.

22:49 amalloy: &(let [x (keyword "test") y (keyword "test")] (time (dotimes [_ 1e7] (= x y))))

22:49 lazybot: ⇒ "Elapsed time: 63.097127 msecs" nil

22:49 amalloy: &(let [x (str "te" "st") y (str "te" "st")] (time (dotimes [_ 1e7] (= x y))))

22:49 lazybot: ⇒ "Elapsed time: 1080.501377 msecs" nil

22:49 amalloy: zakwilson: fast comparisons is practically the reason keywords exist

22:51 zakwilson: amalloy: I don't think I still have my benchmark code around, but keyword lookups in maps were a lot slower under certain circumstances when I tested it last.

22:51 amalloy: &(let [x "test" y "test"] (time (dotimes [_ 1e7] (= x y))))

22:51 lazybot: ⇒ "Elapsed time: 71.512589 msecs" nil

22:52 amalloy: in this case strings are about the same because they're interned class-constants

22:53 but in general comparing keywords is extremely fast, and comparing strings *might* be extremely fast. if you were seeing bad performance it seems likely you were creating keywords on the fly or something

22:54 (which congomongo does, of course, when it converts strings to keywords)

22:56 zakwilson: &(time (let [x :foo y (hash-map :foo 4 :bar 8 :qux 2)] (dotimes [_ 1e7] (y x))))

22:56 lazybot: ⇒ "Elapsed time: 943.981712 msecs" nil

22:56 zakwilson: &(time (let [x :foo y (hash-map :foo 4 :bar 8 :qux 2)] (dotimes [_ 1e7] (y x))))

22:56 lazybot: ⇒ "Elapsed time: 812.843381 msecs" nil

22:56 zakwilson: &(time (let [x "foo" y (hash-map "foo" 4 "bar" 8 "qux" 2)] (dotimes [_ 1e7] (y x))))

22:56 lazybot: ⇒ "Elapsed time: 442.546335 msecs" nil

22:57 zakwilson: That code does not, as far as I understand it create keywords on the fly.

22:58 ibdknox: hm

22:59 it's nearly 2x on locally for me too

22:59 -on

22:59 zakwilson: And it's more on big maps - IIRC something like 5x or 7x.

23:00 ibdknox: hm

23:01 amalloy: interesting. i guess i've got some source-reading to do

23:01 ibdknox: there seems to be a huge difference between using (hashmap...) and just using the literal

23:01 amalloy: ibdknox: the literal is an array-map

23:01 ibdknox: ah

23:02 fwiw

23:02 in that scenario it's about a 3x diff

23:02 but the overall number is much lower

23:02 ,(time (let [x "foo" y {"foo" 4}] (dotimes [_ 1e7] (y x))))

23:02 clojurebot: "Elapsed time: 603.974 msecs"

23:02 ibdknox: ,(time (let [x "foo" y {"foo" 4}] (dotimes [_ 1e7] (y x))))

23:02 clojurebot: "Elapsed time: 1031.745 msecs"

23:03 ibdknox: &(time (let [x "foo" y {"foo" 4}] (dotimes [_ 1e7] (y x))))

23:03 lazybot: ⇒ "Elapsed time: 234.443206 msecs" nil

23:03 ibdknox: there we go

23:04 zakwilson: Strings are faster than numbers too.

23:04 &(time (let [x 1 y (hash-map 2 4 1 8 8 2)] (dotimes [_ 1e7] (y x))))

23:04 lazybot: ⇒ "Elapsed time: 790.373633 msecs" nil

23:04 ibdknox: now that doesn't make sense to me at all

23:04 zakwilson: Nor to me.

23:04 amalloy: zakwilson: sure, that makes sense

23:04 ibdknox: lol

23:04 amalloy: how so?

23:05 amalloy: because you're comparing interned string literals; they just do a pointer-equality check first, which succeeds

23:05 hugod: I wonder how long it takes jit to realise that the result of (y x) is not used and turn it into a nop

23:05 amalloy: numbers have to be checked for type, unboxed, and then compared

23:06 ibdknox: mm

23:06 zakwilson: &(time (let [x (int 1) y (hash-map (int 2) (int 4) (int 1) (int 8) (int 8) (int 2))] (dotimes [_ 1e7] (y x))))

23:06 lazybot: ⇒ "Elapsed time: 1155.865792 msecs" nil

23:06 zakwilson: Explain that one?

23:07 amalloy: you gave the compiler more boxing to do

23:07 you explicitly made x a primitive int, and then to look it up in y you have to box it every time

23:08 &(time (let [x 1 y (hash-map (int 2) (int 4) (int 1) (int 8) (int 8) (int 2))] (dotimes [_ 1e7] (y x))))

23:08 lazybot: ⇒ "Elapsed time: 876.695437 msecs" nil

23:08 zakwilson: Can Clojure maps use a primative as a key?

23:08 amalloy: the other int calls are immaterial

23:08 no

23:08 ibdknox: ah, that was the important bit I was missing

23:09 amalloy: ibdknox: they're Map<Object, Object> and int isn't an Object

23:09 zakwilson: Right.

23:09 ibdknox: indeed not

23:09 wouldn't string always be the fastest possible solution then?

23:10 amalloy: ibdknox: only if all the strings are known at compile time, or interned later

23:10 which is exactly what keywords do, so i'm sorta puzzled as to why they're not fastest

23:10 zakwilson: What would cause them to be interned later?

23:12 amalloy: &(let [x (str "a" "b") y (str "a" "b")] [(identical? x y) (apply identical? (map #(.intern %) [x y]))])

23:12 lazybot: java.lang.SecurityException: You tripped the alarm! intern is bad!

23:12 amalloy: well, i guess that makes sense. but in a repl it works

23:12 that is, returns [true false]

23:12 [false true]. i'm a terrible repl

23:14 zakwilson: So you'd have to call intern? (read-string (slurp result-of-spitting-a-map-of-strings)) wouldn't do it?

23:16 amalloy: no

23:16 that is, you would; it wouldn't

23:16 zakwilson: Strings are still faster than keywords in that scenario.

23:18 khaliG: hm, trying to get started with clojurescript is dizzying

23:19 Arafangion: Hmm, clojure depends on libasm-java?

23:19 What's the libasm for?

23:19 amalloy: for er. assembling classfiles. the clojure compiler

23:20 Arafangion: Ah, not asm in the normal sense, then.

23:20 Hmm, looks like I just installed clojure 1.1, that's a tad out of date.

23:20 amalloy: i don't understand what "the normal sense" is, if it's not assembling stuff

23:20 Arafangion: amalloy: Converting assembly to machine code? :)

23:21 sritchie: has anyone in here generated forms using Enlive?

23:21 Arafangion: Hmm, yep, 1.1 is very out of date.

23:22 amalloy: Arafangion: do yourself a favor, don't install any versions of clojure. just install lein and let it get you what you need

23:23 Arafangion: Hmm, where would lein install it to? /opt/clojure?

23:23 I just installed 1.1

23:23 dnolen: damn Overtone #1 on Hacker News, whodathunk

23:24 ibdknox: dnolen: Noir was #1 last week, Overtone #1 this week.... :D

23:24 Arafangion: Clojure 1.1 seems to work very nicely.

23:24 It manages to print "Hello", at least. :)

23:24 dnolen: ibdknox: both deserved!

23:24 ibdknox: Arafangion: that is beyond out of date, don't use it

23:24 Arafangion: ibdknox: Yeah, I found out after I installed it.

23:25 Are there newer debian packages, or should I backport it?

23:25 ibdknox: dnolen: Clojure's getting more and more attention :)

23:25 amalloy: Arafangion: do not install any versions at all, i'm telling you. clojure doesn't need to be installed

23:26 $google clojure leiningen

23:26 lazybot: [Building Clojure Projects with Leiningen « I am Zef] http://zef.me/2470/building-clojure-projects-with-leiningen

23:26 Arafangion: amalloy: You underestimate how easy it is to install with the package manager.

23:26 zakwilson: I have found cake preferable to leiningen, but they both do about the same thing.

23:27 Arafangion: the point isn't how easy it is to install. The point is that you're better off using the build tools than installing it.

23:27 amalloy: Arafangion: you underestimate how irrelevant that is

23:27 ibdknox: lol

23:27 Arafangion: amalloy: Yeah, I've just started to realise that clojure is typically used only as part of a regular java build script.

23:27 amalloy: sudo apt-get install leiningen

23:27 BAM. done

23:27 Arafangion: amalloy: Even better!

23:28 Ah, it's not in stable.

23:28 Well, I'll check out the script. Not interested in using 1.1.

23:28 One thing I noticed when using 1.1, just now...

23:28 amalloy: yeah, i'm not sure what versions of debian it's actually released for. my understanding is that phil did get it released for some version somewhere, at least

23:29 Arafangion: Defining a new function seems to require special syntax, why is the form (defn foo[bar] ...) used, why not: (defn (foo bar) ...)

23:29 ?

23:29 amalloy: but downloading a shell script and asking it to install the package itself is not that hard

23:29 Arafangion: amalloy: Yeah, I'll be doing that.

23:29 Raynes: That isn't a special syntax. That's consistent throughout Clojure.

23:29 amalloy: Arafangion: uh, special syntax?

23:29 Raynes: It's special compared to scheme, maybe.

23:29 Arafangion: Raynes: Yeah, compared to "other lisps".

23:29 ibdknox: uh oh

23:30 zakwilson: Arafangion: the convention in Clojure is that parens are used for things that are evaluated and brackets are used for data.

23:30 Arafangion: zakwilson: Not a bad convention... But why the m-expr form?

23:30 zakwilson: So (defn foo [bar] ...), (let [foo bar] ...)

23:30 Arafangion: it's not m-expr form. It's the same form as Common Lisp (defun foo (bar) ...)

23:30 mabes: Arafangion: the motivation is that Rich believes that overloading parens for function calls, and parameter lists adds complexity and thinks that complexity is one of the main reasons most people complain about parens in other lisps

23:31 Arafangion: zakwilson: s-expr form would be (defun (foo bar) ...), right?

23:31 gregh: don't think of clojure square brackets as m-exprs, since they aren't

23:31 Arafangion: mabes: Not sure I agree with that... But, making use of square brackets is a nice idea.

23:32 gregh: I mean, why do we do foo[bar], rather than [foo bar]?

23:32 zakwilson: Arafangion: both forms are sexps. There's no particular advantage to one form over the other. One is CL-style and the other is Scheme-style.

23:32 gregh: Arafangion: that's just what defn expects

23:32 Arafangion: Is there an implied space between '

23:33 ibdknox: it's a visual distinction

23:33 Arafangion: Is there an implied space between 'foo' and '[bar]'?

23:33 gregh: not sure what that means, since a space there is optional and doesn't affect the meaning

23:33 * Arafangion is someone who has read a lot of lisp papers, but yet to actually use it

23:33 ibdknox: hm lol

23:33 amalloy: Arafangion: no "implied" space is needed - put tokens wherever you want. but usually there is an "actual" space, stylistically, because that's how people write it

23:34 Arafangion: amalloy: Ah, now the world makes sense again. :)

23:34 Without the space, it just looked like an m-expr.

23:34 amalloy: Arafangion: try writing a few lines of clojure before asking why everything is different from...a language you've never actually used?

23:35 Raynes: There was a stackoverflow thread about this, but damn if I can find it.

23:35 Arafangion: amalloy: Touche.

23:35 zakwilson: You could also write (defn foo,[bar] ...) if you wanted.

23:36 amalloy: (defn, ,foo, ,, ,,,,,[,bar],,, ...) is my preferred style

23:36 * ibdknox dies a little inside

23:37 dnolen: ,(,,,,,,,,,,,(fn [a ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, b] (+ a b)) ,,,,,,, 1 ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 1)

23:37 clojurebot: 2

23:37 amalloy: hm. i bet i could write a little program to morse-code the commas and spaces in a clojure program

23:37 "take my existing program and rewrite the spacing so that the commas and spaces, in morse code, spell out this shell script"

23:39 dnolen: Arafangion: reading a lot of Lisp papers w/o using it? that's interesting

23:40 Arafangion: "Take the existing program and modify it subly so that the commas and spaces are a valid Brain**** program" <-- THAT would make me die inside.

23:42 dnolen: I had no opportunity to use it, i was struggling enough with crappy C/VB/C#/Java projects in microsoft-shop/uni.

23:42 dnolen: It's remarkable how lecturers can violate just about every rule and still somehow have a 'working' program.

23:42 ibdknox: One of my favorite non-functionally-related parts of clojure is that I never have to type commas

23:42 Arafangion: At work, I use mostly C#, Python, Ruby, and C.

23:43 And I don't have opportunity to use anything radical there, either.

23:43 dnolen: Arafangion: gotcha. Well if you're using Ruby/Python, you're not so far from Clojure.

23:43 duck1123: ruby was a good gateway to clojure for me

23:44 dnolen: Clojure is built on the lessons of Ruby/Python/JavaScript.

23:45 Arafangion: dnolen: Ruby, perhaps, but python? No, I think it's quite different to clojure.

23:45 dnolen: Arafangion: convenient syntax for data structures

23:45 zakwilson: I really hate going to other languages where I have to type commas in collection literals. It's a trivial irritation, but I still find it really irritating.

23:45 ibdknox: zakwilson: me too

23:46 gregh: especially when you have to omit the last one

23:46 ibdknox: hah

23:46 fuck IE

23:46 that is one of the single most annoying things in all of JS

23:47 zakwilson: Clojure has list comprehensions. I don't think Ruby does. Python does.

23:47 ibdknox: You guys might laugh at this, but C# can actually get quite close to Clojure too

23:47 Arafangion: dnolen: The commas do get in the way.

23:48 ibdknox: Yeah, how so? (But yeah, C# is a remarkably good language)

23:48 gregh: What's especially annoying is when a langauge doesn't let you have a trailing comma. Eg, foo = [1, 2, 3,]

23:49 dnolen: Arafangion: going back a little. I use Scheme/Racket and Clojure. Clojure's take on the number of required parens and syntax around vectors is a real win.

23:49 ibdknox: Arafangion: depending on which version of C# you're using, with LINQ, var, anonymous functions, and collection initializers you can write very clojure-esque code

23:50 dnolen: Arafangion: it's a huge win from a cognitive load stand point

23:50 you can't underestimate the value of conceptual consistency

23:50 dnolen: ibdknox: I believe that. I think that people focus on Clojure differences, rather than how much it draws in Good Ideas™ from many mainstream languages.

23:50 Arafangion: ibdknox: Yes - I do use a LOT of C# 4.0

23:51 dnolen: Yes, I like the idea of providing convenient data structures via []'s.

23:51 (Or whatever the syntax is)

23:52 dnolen: Clojure from one stand point is - Maintstream Good Idea Goldmine™

23:52 ibdknox: dnolen: yeah, that makes me sad. I mean even if you just step back and look at it without trying to understand it, it's much easier to section of and group things usefully without even really knowing what it is.

23:52 off*

23:52 zakwilson: When will we see atoms and agents in other languages?

23:56 Arafangion: zakwilson: By what definition?

23:57 ibdknox: Completely unrelated, but the fact that this can be written in so few lines of code should blow your mind: http://mbostock.github.com/d3/ex/voronoi.html

23:57 zakwilson: Arafangion: Clojure has constructs called atoms and agents. You can read about them on clojure.org - that explanation will be far better than any I could give.

23:57 ibdknox: it cheats, but still

23:58 zakwilson: I thought there was an attempt to do something like the in Scala, but I can't remember what it is called

Logging service provided by n01se.net