#clojure log - Oct 30 2009

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

0:00 gerry_: ok,not use println

0:02 not use println is 35 vs 44

0:02 Knekk: see?

0:03 gerry_: about 20% boost

0:03 i thought it should be > 40% :)

0:04 Knekk: increase to 500k iterations? Does your ratio hold?

0:05 gerry_: let's try

0:06 206 vs 256

0:06 still about 20%

0:06 Knekk: ok

0:07 dunno. you should ask someone who knows the internals about your missing improvement

0:07 gerry_: AwizzWard?

0:15 chouser's patch still not used yet?

0:20 Raynes: Apparently, the bleeding edge VimClojure works fine for me. It's a little inconvenient to have to have any file you edit on the classpath, but I'll manage.

0:20 nroot: Hi I am new to clojure, but I have some experience in Erlang and Map reduce. The reason I am learning clojure is because it is said that it is build for concurrency from ground up.

0:20 My question is what is it parallelism model, is it thread based ? Meaning it will only work on machine with large number of cores or is it map reduce like meaning it can work on large number of machines with each having 1 or 2 cores.

0:20 tomoj: oh, damn

0:21 the error I was having with c.c.http.agent was because I changed something in there to intentionally cause an error so I could see the backtrace, and forgot to change it back

0:21 gerry_: oh,that's 217 vs 304

0:22 about 40% great

0:22 tomoj: nroot: clojure's concurrency model is based on threads

0:22 it doesn't do anything at all to help you with distributed computing

0:23 nroot: tomoj: so it can not exploit working on something like google app engine

0:23 tomoj: in fact rhickey thinks it's outright impossible to do what clojure does for distributed computing

0:23 I dunno anything about google app engine

0:24 gerry_: minibenchmark result: deftype about 40% faster than defstuct

0:24 tomoj: if you have a multi-threaded application clojure will help you deal with the problems that usually arise with multi-threaded applications and state

0:24 nroot: tomoj: thanks

0:24 technomancy: tomoj: "outright impossible" is strong wording... he's just said that it doesn't belong in the core language

0:25 tomoj: no, he said it's "doomed"

0:25 I'm not talking about distributed help in general, just that he said trying to do what clojure does for multi-threaded state in a distributed way is doomed

0:25 certainly we can build some clojure tools that help with distributed computing

0:26 technomancy: oh sure, but that's kind of tautological.

0:26 "providing tools to help with shared mutable state is impossible when there's no shared state."

0:27 tomoj: heh, yeah

0:27 but I'm sure he didn't mean a tautology when he said it

0:27 I just am too noob to say it right

0:27 the statements I'm talking about are in http://www.infoq.com/presentations/Value-Identity-State-Rich-Hickey

0:27 technomancy: hehe

0:27 chouser: nroot: There are several projects that are working to help make it easy to distribute Java work across multiple machines

0:28 nroot: chouser: like ?

0:28 chouser: Clojure can take advantage of some of these already, and will do more in the long run

0:28 The one that comes to mind is Hadoop, but there are others.

0:29 I think there's also one that may be pure Clojure. http://github.com/amitrathore/swarmiji

0:30 leif-p: I believe one company is already using clojure with Hadoop + Cascading for their data processing.

0:31 chouser: But Clojure itself is more concentrated on the multicore/multithreaded model where you can read memory more cheaply than passing messages to another process, and don't have to worry about the same failure cases as distributed systems.

0:31 wooby: nroot: clojure runs fine on app engine

0:32 nroot: although the STM is busted because of the way google deploys stuff

0:33 tomoj: my neural networks where each node has a seq of references to other nodes: buggy

0:33 wooby: nroot: http://elhumidor.blogspot.com/2009/04/clojure-on-google-appengine.html

0:33 tomoj: my neural networks where each network is a single immutable value: not buggy

0:33 :D

0:33 wooby: tomoj: what kind of network?

0:34 tomoj: like, sum the inputs and run them through a sigmoid

0:34 technomancy: terracotta, JMS, AMQP

0:34 AMQP is language-agnostic

0:34 but works great with Clojure

0:34 yeah, that wraps AMQP actually

0:34 anyone want to test out my swank-clojure 1.0 release candidate?

0:34 should be an even easier install than M-x clojure-install

0:34 google disallows new threads, so STM is not that interesting without that

0:34 wooby: i was working on something like that the other day, from turing omnibus

0:36 tomoj: mine are fully lazy (i.e. cache each node's activation in an edge before passing it on to the next node) to support abitrary topologies

0:36 working on implementing ken stanley's NEAT

0:37 wooby: tomoj: i would be very interested in seeing that, if you're willing to throw it up somewhere

0:37 piccolin1: technomancy, heck yes!

0:38 tomoj: wooby: it will be thrown up soon once I iron out a couple problems

0:38 wooby: awesome

0:38 tomoj: eventually want to do HyperNEAT

1:34 Clips: www.socialchat.co.uk or irc.socialchat.co.uk

1:34 Join now :) Swearing allowed

2:02 tomoj: is there a better way to write (fn [a b] [a b]) ?

2:03 hiredman: vector

2:03 tomoj: aha

2:03 thanks

2:03 hiredman: ,(vector 'a 'b)

2:03 clojurebot: [a b]

2:03 tomoj: I knew of vec, but not vector

2:04 hiredman: ,((juxt (comp first list) (comp second list)) 'a 'b)

2:04 clojurebot: [a b]

2:04 tomoj: ,(map vector [1 2 3] [4 5 6])

2:04 clojurebot: ([1 4] [2 5] [3 6])

2:04 tomoj: nifty

2:05 juxt is cool too

2:32 qed: man it sucks that have this friend who who goes out of his way to refuse that clojure is worthwhile

2:32 that I have this*

2:33 as usual, our drink turned into a discussion about programming, and i bring up how I think clojure is sort of the future programming language in that many of its features will be implemented into the mainstream at one point or another

2:34 he is of the mind that if you aren't writing C you're wasting time, so I bring up abstraction and how it's important, but he seems dead set on this notion that concurrency and all of the things that clojure brings with it are glitter, without substance

2:35 can anyone offer me anything in the way of perspective?

2:35 am i being too bold when it comes to clojure?

2:37 it just seems like the most elegant language ive ever used, how could anyone who hasn't used it have any idea?

2:37 arbscht: qed: if I were you, I'd have focused on enjoying the drink and not arguing about programming :)

2:37 piccolino: You'd be surprised what some people just can't be convinced of.

2:38 qed: arbscht: good advice, good advice, sigh, im not trying to convince so much as im just trying to gain some sort of recognition

2:39 he's so ill-informed, though, that when i try to explain certain concepts he just dismisses them because he doesn't know them

2:39 arbscht: qed: write some useful code, it is more satisfying than recognition of the merits of a system in the abstract

2:39 piccolino: Punish him by letting him remain ignorant.

2:39 qed: piccolino: haha, arbscht: no doubt

2:39 tomoj: qed: has he written a multi-threaded C program?

2:40 qed: tomoj: he claims to know mutexes and thread locking, but i highly doubt he knows what lies in that clusterfuck

2:40 tomoj: ah

2:40 have him try to write ants.clj in C

2:40 qed: now that is a gauntlet! :)

2:41 tomoj: keeping the idea that each ant runs on a separate thread

2:41 qed: his main argument was this:

2:41 tomoj: I guess maybe you could do it OK since ants.clj is not very complex

2:41 qed: the difference between making your program concurrent and running it fast with C is negligible

2:41 tomoj: I have never done much multi-threaded stuff

2:41 hahaha

2:42 did you remind him about the end of moore's law?

2:42 qed: tomoj: lol, omg that would have destroyed him

2:42 i wouldn't have a friend anymore if i reminded him of *that*

2:42 he would have been so butt hurt he probably would have stormed off with a curly bracket and a semicolon

2:43 tomoj: if program B runs faster than program A by a constant factor, but B only runs on one core, and A runs on 64 cores...

2:44 I actually only have one core here :(

2:44 but it pretends like it's two cores or something strange like that

2:45 anyway I guess pretty soon everyone will have 8+ cores?

2:45 qed: tomoj: i just sent that to him via im

2:45 his response is: "that's really a kernel thing, the kernel schedules the usage of all the processors"

2:46 "if you create a thread it will be automatically scheduled and used on any available processors"

2:46 "it's not like your code has to be any more complex"

2:47 tomoj: I conclude he has never done any serious multi-theaded programmming

2:47 though neither have I, so what do I know

2:48 but the problem is, of course, these threads will want to access the same memory (in C)

2:49 qed: his response: "yeah that's why you write thread-safe code"

2:49 tomoj: exactly

2:50 the question is HOW

2:50 in clojure it's easy

2:50 in C...?

2:50 qed: he's clueless and stubborn

2:51 tomoj: eh

2:51 qed: i know him very well, he really lashes out against anything he doesn't know already

2:51 tomoj: guess it's like the Blub programmer

2:52 everything I've ever done, I've been able to do with ruby/clojure/CL/java, so anything else is useless

2:54 or rather, not any MORE useful than what I've got

2:54 qed: he just told me: "build me an operating system in clojure"

2:54 hiredman: qed: I will

2:54 just give me some time

2:55 wooby: clojurebot nearly is

2:55 hiredman: http://research.sun.com/projects/dashboard.php?id=185

2:55 wooby: i saw that the other day, so awesome

2:55 hiredman: http://research.sun.com/spotlight/2008/2008-08-13_maxine.html

2:55 tomoj: hmm

2:56 hiredman: really, I want maxine, the guest os thing is just kind of cool

2:56 tomoj: is the test of a programming language's usefulness whether or not one can build an OS using the language?

2:56 hiredman: I know headius is looking at maxine for jruby

2:57 qed: dude, he just logged off: "but seriously, don't fucking tell me i have no perspective because i'm not balls deep in some obscure shit"

2:57 "you're pissing me the fuck off"

2:57 /quit

2:57 tomoj: hehe

2:57 qed: lol, one less friend

2:57 more time to code

2:57 tomoj: developers can be quite defensive

2:58 qed: yeah, he's totally on that game, i welcome whatever i can find that's new and weird and obscure and challenging, etc.

2:58 it's just my nature

2:58 i truly don't understand the other end of that spectrum

2:58 "what i have is good enough for anyone!"

2:58 wtf?

2:58 no. it's not.

2:59 i think what pisses him off more than anything, is that he has a veryyyyy formal CS education, but he knows about the same as me

3:00 so he feels like he has this platform to accept or reject ideas i propose when it comes to CS

3:01 like he is the high court of CS, and his decree will be the law of the land

3:03 idk, just another typical CS student who believes they wont need to learn anymore after they finish college

3:05 universities are filled with so much garbage these days

3:05 sigh, im rambling

3:05 sorry all

3:21 sfuentes: qed: that's a bit extreme there

3:22 qed: sfuentes: ?

3:22 the university bi?

3:22 bit?

3:22 I just meet a lot of undergrads these days who have no passion--

3:22 sfuentes: personally, i think a lack of a software engineering curriculum is at work

3:22 qed: that's certainly true

3:23 it's like this weird hermaphrodite balance between djikstra and kay

3:23 tomoj: all of the CS majors I know are shitty developers

3:23 qed: (curriculum-wise)

3:23 tomoj: same here

3:23 like practically inept

3:24 tomoj: I like the CS curriculum just fine, though

3:24 I enjoy abstract stuff that has no practical application :)

3:24 qed: there is less than 20% of CS majors I've seen who could hack

3:24 like-- really... hack.

3:24 arbscht: irc channels are filled with garbage these days; I think a lack of coding is at work ;) (does clojure make programming useful things so trivial that you have time for this?)

3:25 qed: arbscht: bourbon, ginger beer, and bitters -- will do this to a man

3:25 tomoj: someone just peed off the balcony above me

3:25 qed: tomoj: welcome to halloween'

3:25 i live in madison, wi

3:25 sfuentes: i think there should be a "software school" (similar to law and medical school) after one gets their CS degree.

3:26 qed: sfuentes: that's a really good idea

3:26 tomoj: not sure you can really learn much without actually doing

3:26 sfuentes: tomoj: but you *will* be doing

3:26 tomoj: if it's a school, you won't

3:26 qed: our CS program emphasized group work to get the "software development" "real world" scenario

3:26 but it was BS

3:26 tomoj: unless the school is really just an internship

3:27 qed: half the time your partner wouldn't do anything

3:27 and you'd pull the team

3:28 tomoj: I wonder how many clojure dev shops there are

3:28 qed: probably not many

3:28 id love to be a part of one

3:28 sfuentes: tomoj: Residency training

3:29 tomoj: yeah, isn't that what an internship is?

3:30 sfuentes: internships are very general

3:30 not very supervised

3:30 but yes

3:31 tomoj: they can be useless I suppose

3:32 I work for the IT dept of my university and there's very little source control, absolutely no testing, and absolutely no pair programming

3:32 qed: :X

3:32 i have to go to bed, it's late

3:32 but we will continue this tomorrow :)

3:33 ciao tomoj, sfuentes

3:33 tomoj: co'o

3:34 sfuentes: night qed

3:34 tomoj: sad to hear

3:34 then again its IT

3:35 tomoj: I am now wondering whether the liquid that just fell from above onto my shoes is piss or a drink :(

3:56 arbscht: tomoj: don't evaluate it, it might have side effects!

3:59 tomoj: afterwards someone said "oh I didn't realize there was a drink next to you sorry" so I think I'm OK

4:58 yason: Is Clojure good at optimizing out multiple funcalls and replacing them with the value returned from a single funcall?

4:59 (let [x (compute-something)] (list x x)) versus (list (compute-something) (compute-something)) ?

5:03 cgrand: yason: no because clojure can't generally know if a function is pure

5:05 yason: cgrand: No metadata for annotating pure functions? Ok, so (let ...) it is.

5:05 Avoiding let would've made a more beautiful look though, in this case :)

5:06 cgrand: (repeat 2 (compute-something))

6:18 AWizzArd: How can I type hint a parameter to be a function object?

6:21 ah okay, it's #^clojure.lang.Fn

6:28 morning

6:31 modulus: hey, some good doc to read on the deployment of clojure and ides and stuff?

7:06 Kjellski: Gooood, morning!

7:24 AWizzArd: Hi the Kjell.

7:43 rhickey: deftype/defclass print is up - thanks to chouser!

8:01 blackdog_: hi, in slime/swank is there a way to add a directory of jars all at one time to the classpath, rather than enumerating each

8:05 _ato: blackdog_: (setq-swank-extra-classpaths '("~/somewhere/*"))

8:06 blackdog_: ah thanks :)

8:06 _ato: assuming you're using java 6, I don't think it works in earlier versions

8:06 blackdog_: yes

8:23 eevar2: with java 1.5 you'd do (setq swank-clojure-extra-classpaths (cons "/opt/clojure-contrib/clojure-contrib.jar" (directory-files "/opt/clojure-libs" t ".jar$")))

8:23 damn old macbook.. :/

8:32 AWizzArd: chouser: cool, thanks for the printing

8:33 rhickey: is the PAR branch (git) dependend on some external libs? Can it get merged with the NEW branch?

8:34 rhickey: AWizzArd: it depends on jsr166y

8:35 AWizzArd: http://www.jcp.org/en/jsr/summary?id=166

8:35 rhickey: the dep is here: http://github.com/richhickey/clojure/downloads

8:36 http://cloud.github.com/downloads/richhickey/clojure/jsr166y.jar

8:40 AWizzArd: Do you think the .class files from that .jar may get included in future versions of Clojure?

8:49 rhickey: AWizzArd: jsr166y is not compatible with Java 5

8:51 AWizzArd: I see

8:53 chouser: bah

8:53 rhickey: chouser: good morning to you too :)

8:53 chouser: rhickey: sorry about the load order. I forgot to actually try building clojure before putting the patch up.

8:54 heh. good morning. :-)

8:54 rhickey: np

8:54 notallama: jsr166y.jar seems to be missing things. namely, jsr166y.forkjoin.*

8:58 rhickey: notallama: compared to what? there may have been some refactoring since I snapshotted, but that is all that par needs

8:58 forkjoin was moving target at the time

9:00 so, the new deftype/defclass theory is, if you want IPersistentMap support generated, just specify it in the interface list but don't implement it

9:00 by default only hash,equals, metadata and lookup are included

9:02 notallama: rhickey: compared to what parallel.clj is asking for. (import '(jsr166.forkjoin ...))

9:03 rhickey: notallama: parallel.clj was written to a very old jsr166y, available here: http://clojure.googlegroups.com/web/jsr166y.jar

9:04 the old and new libraries are incompatible, that was the last version to work with Java 5

9:05 so par will replace parallel at some point

9:05 hoeck: rhickey: what about adding IObj/IMeta to the list of magically implemented interfaces?

9:05 rhickey: hoeck: meaning no default generation?

9:05 hoeck: rhickey: or is this a must so that the type tag works?

9:06 rhickey: yes, say for some extreme lightweigt types, like database-rows

9:06 rhickey: who doesn't want metadata?

9:06 notallama: oh, so parallel isn't par. that explains things

9:07 rhickey: hoeck: seems like a premature optimization

9:07 as database rows flow through an app, you sure might want to remember what table they came from etc

9:07 hoeck: rhickey: okay, guess I will measure then :)

9:07 rhickey: hoeck: certainly only a space issue

9:08 hoeck: rhickey: ok, point taken, but whats the reason to optionally implement IPersistentMap?

9:09 rhickey: but there will at lest be a consistent construction story, regardless of which interfaces are implemented - fields you asked for + meta + extmap, the latter 2 defaulting to null

9:09 AWizzArd: Btw, what advantages does defclass offer over deftype?

9:10 chouser: AWizzArd: named class and (maybe) more speed

9:10 rhickey: hoeck: IPersistentMap brings a ton of semantics - it essentially makes your type/class a collection - collection, Counted, Seqable, associative etc

9:10 AWizzArd: chouser: named class - so one can add type hints in functions that take defclassed objects?

9:10 chouser: I noticed defclass only made one ctor.

9:11 AWizzArd: well, so that Java can use it by name, find the class file by name, etc.

9:11 rhickey: chouser: yes,I need to fix that, copied from deftype

9:13 chouser: I couldn't see where the ctors were specified

9:13 rhickey: defclass docs

9:14 chouser: I mean I didn't see where create-defclass* was told what ctors to create so I thought maybe it was all in Compiler ...and promptly stopped digging.

9:15 rhickey: chouser: yes, compiler does the ctor from fieldslist supplied to defclass*

9:15 chouser: yeah, ok. will deftype classes get 2 ctors also, or will there have to be another arg to defclass*?

9:17 rhickey: chouser: no, there's only one ctor, 2 factory functions - the docs are wrong because I copied factroy-ctor from deftype docs to defclass docs

9:18 chouser: ahhhh. ok.

9:18 rhickey: right now there isn't accessibility to the deftype ctor for code not inside deftype

9:18 chouser: right

9:18 rhickey: becasue the actual classname doesn't escape

9:19 so, dissoc of base field --> ordinary map not of type?

9:19 I like that better than error, if e.g. get of non-present is going to return nil

9:21 chouser: doesn't it seem a little scarey that all the behavior (besides IPersistentMap) could change on dissoc?

9:21 rhickey: chouser: it's a different object

9:21 chouser: hm -- regular map but keep the type :tag?

9:22 rhickey: chouser: it's not the same type anymore

9:22 if you are calling dissoc you are treating the class as a collection/data

9:22 i.e. more generically

9:23 code in set or relational libs might do that just as a matter of transformation

9:23 this thing without those fields merged into that thing

9:24 shouldn't blow up if this-thing is from a deftype

9:25 * rhickey using cemerick's argument against him...

9:30 AWizzArd: Is it/will it be possible to define a hierarchy with deftype/defclass?

9:30 rhickey: AWizzArd: a hierarchy of concrete types ? no

9:33 hoeck: rhickey: but a hierarchy of interfaces?

9:33 AWizzArd: Maybe one can use derive and isa??

9:34 hoeck: and how do I define Interfaces? with gen-interface?

9:35 rhickey: hoeck: it's possible, and I've done it, but it's almost always better not to. You end up doing in in Java because you couldn't say foo(this-and-that-type x), maybe now with generics you can

9:36 hoeck: there will be a definterface that matches defclass/type, but same idea, and same AOT

9:36 AWizzArd: you should avoid hierarchy when you have other tools to model overlapping concerns - like protocols :)

9:40 jdirks: Hi there anyone willing to answer my noob questiosn?

9:42 How do i make a set from a list? #{ (list 1 2 3 4) } makes a set that contains 1 list element.... not what I want.

9:42 chouser: ,(hash-set (list 1 2 3 4))

9:42 clojurebot: #{(1 2 3 4)}

9:42 chouser: d'oh

9:42 ,(set (list 1 2 3 4))

9:42 clojurebot: #{1 2 3 4}

9:44 hoeck: rhickey, so the clojure interface-hierarchy will be defined in terms of `protokolls', cool

9:45 esj: is there a reference out there explaining protocols in this sense ?

9:45 AWizzArd: rhickey: ok, I still don't have protocols on my radar yet.

9:46 esj: http://www.assembla.com/wiki/show/clojure/Protocols

9:46 esj: AWizzArd: much obliged

9:50 jdirks: I notice set creates a PersistentHashSet and sorted-set creates a PersistentTreeSet. Is there a way to create a PersistentTreeSet with a function like set that can take a list?

9:50 _ato: ,(apply sorted-set (list 1 2 3 4))

9:50 clojurebot: #{1 2 3 4}

9:51 _ato: ,(type (apply sorted-set (list 1 2 3 4)))

9:51 clojurebot: clojure.lang.PersistentTreeSet

9:53 jdirks: Anyone know why 'set' can be called directly but union only works with 'clojure.set/union' ? It seems a bit inconsistent.

9:56 chouser: jdirks: you're asking why some set-related functions are in clojure.core and others are in clojure.set ?

9:57 jdirks: I know it is just a design issue but it seems that set and union really should go together.

9:58 I was wondering if there was some real reason for the different name space

9:58 especially since it is not documented that way at http://clojure.org/api#union

9:59 _ato: it is, scroll up and you'll see it's under a clojure.set heading

10:00 rhickey: jdirks: actually, that is in it's own section, per namespace, just not great graphically

10:00 chouser: the basic functions you need to work with the set datatypes are all in core -- set, hash-set, sorted-set for creation; get, contains?, conj, seq for working with existing ones.

10:00 rhickey: above difference - clojure.set

10:01 jdirks: oops sorry

10:01 rhickey: chouser: thanks for deftype print - so much nicer to play with now!

10:01 jdirks: i guess if you only use search on that page you do not notice it is organized that way.

10:01 chouser: the clojure.set namespace has "extra" stuff for working with set objects -- mostly relational things (join, select) and their support functions, but some others as well.

10:01 gerry_: hello

10:01 chouser: rhickey: heh, np.

10:02 rhickey: will you be wanting a reader?

10:02 gerry_: my os crashed, i have to reinstall it to check out clojure-new and try again

10:02 rhickey: so, (deftype Foo [a b c d e] [IPersistentMap]) in order to get associative/expando?

10:03 chouser: rhickey: is that instead of any opt-out flags?

10:03 rhickey: chouser: at some point I guess at least print-dup/readable, but complications exist regarding the availability of the supporting code needed to create instances

10:03 chouser: yes, instead of opt out or int

10:04 in

10:05 chouser: can we have clojure.lang.* imported by default? or maybe shortcut names for use in the deftype/defclass interfaces list?

10:06 (deftype Foo [a b c] [:map :stack :reversible java.util.Foo])

10:09 Kjellski: Anyone that saw a good comparison for Clojure ans Scala? Where the main differences are?

10:10 gerry_: hmm

10:10 chouser: Kjellski: Clojure, when compared objectivly and rigerously to Scala, has more good and less bad

10:10 _ato: hehe :)

10:11 Kjellski: *smile* write this in the #scala and get on with the flamewar right?

10:11 rhickey: chouser: I like the abstracting away of the interfaces in that, but it has to be clear what you get, and what will conflict if self-defined

10:11 jdirks: I would say Scala is Java++. Clojure is a functional language that runs on the JVM.

10:11 magnet: chouser, that's objective

10:12 gerry_: kjellski: search on stackoverflow.com

10:12 chouser: magnet: exactly. and rigorous

10:12 Kjellski: gerry_ : thanks, nice tip.

10:13 magnet: Kjellski, my comparison is: Clojure is a Lisp. Scala is not. If you like Lisp, use Clojure. If you prefer ML use Scala.

10:14 rhickey: chouser: :keys in interface list might be useful as an extension point as well

10:14 chouser: Kjellski: Clojure has: dynamic types, macros, smaller core, more emphesis on immutability, richer concurrency semantics, more broadly useful seq abstraction.

10:15 Kjellski: chouser : And what of that does Scala have not?

10:15 chouser: rhickey: yeah, the mapping of short key to interface name isn't terribly obvious. auto-importing clojure.lang would be less magical

10:16 Kjellski: chouser : Okay, macros I know... ^^

10:16 chouser: Kjellski: those were as compared to Scala

10:16 Kjellski: chouser : you really think, that is all better in clojure?

10:17 chouser: Well, Scala is staticlly typed and has no macros, so that's easy.

10:17 Kjellski: k

10:17 jdirks: Is there any work being done on getting some sort of stack trace when you hit an exception? Especially since I am new I find that I need to test every little bit of logic separately because if there is a runtime exception I can not find where it happened exactly.

10:18 (This was never a problem when using Python)

10:18 _ato: jdirks: huh? you should be getting a stack trace, with the file and line number

10:18 chouser: The Scala type system is quite complex, the compiler would have to be more complex, and I think the standard library is larger, so you can file all that under "larger core"

10:18 Chousuke: you may need to use (.printStackTrace *e) after the exception

10:19 or, even better, use the contrib stacktrace pretty-printing thing to do that.

10:19 jdirks: ok I may have missed something. Is there a long to how to do that?

10:19 raek: jdirks: if you are using emacs, I recommend slime over inferior-lisp

10:19 chouser: Kjellski: Scala does support immutable locals and has some immutable collections, but it also has mutable locals and mutable collections. Clojure provides only immutables -- so "more emphesis on immutability"

10:19 jdirks: I currently use the Eclipse plugin

10:20 Kjellski: chouser : don´t stop, I´m reading ^^

10:20 raek: I'll guess it depends on the IDE you are using

10:20 cemerick: rhickey: perhaps you could relent on open imports just for clojure.lang. Maybe an :import-clojure form in ns?

10:20 magnet: chouser, the fact is in both Clojure and Scala you can fall back to Java and end up with mutable structures. Scala made the choice to provide some (Scalified) of its own, whereas Clojure put a barrier and said "here be dragons; we do not compromise" :)

10:20 Chousuke: also: scala syntax. :-(

10:21 ambient: well, clojure has arrays for fast mutable access, which for my purposes are a bit clunky

10:21 magnet: Chousuke, a lot of people would say; also: clojure syntax :-( ;)

10:21 Chousuke: magnet: but they would be mistaken!

10:21 rhickey: cemerick: I really don't want people to marry all of clojure.lang, or possibly any of it

10:21 chouser: Kjellski: If you want to write multithreaded apps, Clojure allows you to choose for each taks between: agents (a bit like Scala's actors), atoms, refs (the main STM hook -- no such thing in Scala), vars (easy access to thread-local data) -- thus "richer concurrency semantics"

10:21 jdirks: Then again you can do OO in Scala.

10:21 Chousuke: well, except for a few things

10:21 #() can get ugly sometimes

10:22 magnet: chouser, I hear Scala developers are planning for a STM in 3.0

10:22 cemerick: OK. I was just reacting to chouser's ":map :stack :reversible" example.

10:22 rhickey: cemerick: but the interfaces could be auto-included with the java.lang bits

10:22 magnet: chouser, but I agree with you that chouser provides more support currently

10:22 chouser: magnet: yes, and I appreciate the pragmatism of both. But when speaking of the language itself I think it's still accurate to say Clojure puts "more emphesis on immutability"

10:22 right

10:23 rhickey: cemerick: one nice aspect of :map etc is that it doesn't dictate that the support will be provided via interfaces. Once those features are supported via protocols they could be provided wither way

10:23 raek: Kjellski: macros are one of my favorite things in lisps. if the code is starting to look complex, simplify it with macros

10:23 Chousuke: it's not even possible to use most of the concurrency stuff if you're not using immutable data structures :/

10:23 markgunnels: adf

10:23 raek: (a (b (c (d (e))))) => (-> e d c b a)

10:23 magnet: raek, macros are also a thing a lot of people tend to get wrong in Lisp

10:24 "with a great power comes great responsibilities ;p"

10:24 raek: hehe

10:24 that's true...

10:24 chouser: Kjellski: that leaves the seq abstration. Scala does have lazy Streams, but they're their own thing with a few methods. Clojure's seq library is pervasive and shouldn't be underestimated in it's power.

10:25 magnet: chouser, actually that changed in 2.8 with the new scala collections

10:25 rhickey: cemerick: so, you are ok with (deftype Foo [a b c d e] [IPersistentMap]) in order to get associative/expando?

10:25 Chousuke: but macros are one tool that you want to have.

10:25 cemerick: rhickey: oh, that's just fine :-)

10:26 esj: the only trouble with Clojure, is that for beginners, such as myself, learning Clojure, requires learning three languages (clojure, java, lisp) more or less concurrently, which is a mild challenge

10:26 chouser: Kjellski: every collection type knows how to be viewed as a seq, the set of functions that work on seqs are powerful and succinct, and all the persistent collections can be built from seqs. It's really a beautiful thing for expressing data transformations, and you get to use it just about anywhere.

10:26 Kjellski: chouser : Thanks a lot for this nice wrappup! I´ll definitely save this log. That´s what I was looking for.

10:26 raek: is there any way to read, say words or other tokens, from a java InputStream using a seq?

10:26 Chousuke: sure.

10:27 chouser: magnet: oh, which changed? I've been away from Scala a while.

10:27 magnet: chouser, pretty much everything in collections. Odersky remade them more or less from scratch

10:27 chouser: Kjellski: oh, and a final killer feature for me that Scala just can't touch: commit access. ;-)

10:27 Chousuke: first you read a seq of characters, then send that through a filter which tokenizes the seq, and then you have a seq of tokens :P

10:27 rhickey: cemerick: and dissoc of base key yielding non-type map?

10:28 cemerick: rhickey: yes, definitely. It's probably an opinionated choice w.r.t. type theory, but I think it's the right one, anyway.

10:29 Kjellski: chouser : Sure, that´s pretty nice... but there is no way to get involved in Scala?

10:29 magnet: Kjellski, define "get involved"?

10:29 ah

10:29 Kjellski: got it?

10:29 magnet: well sure, there are some external committers for scala too :)

10:29 raek: Chousuke: how do I get a seq from a stream?

10:29 rhickey: hmm... 30+ interfaces in clojure.lang

10:29 magnet: Kjellski, didn't see chouser's line :)

10:29 chouser: Kjellski: oh I'm sure there is, but I'm "in" here already. :-)

10:29 raek: is there anything like that in the core api?

10:29 Kjellski: magnet : okay.

10:30 Chousuke: raek: well, for example, (repeatedly #(.read stream))

10:30 raek: ah, ok. that was pretty simple

10:30 Kjellski: chouser: And, please stay here =)

10:30 Chousuke: that produces ints though

10:30 magnet: Kjellski, a huge argument in favor of Scala is that, I believe it's easier to get Java/C++ programmers to move to Scala than to Clojure, at least currently.

10:30 but that's only my personal experience

10:31 Chousuke: magnet: I don't think that's a real pro, though :/

10:31 Kjellski: magnet : I think so too, but the hard time I have now, will be forgotten when I´m used to write Lisp code... I just need the "paranthesis from my father" ^^

10:31 magnet: Chousuke, well it's a pro when you get your boss to agree to use Scala on a project because "even if I'm gone, people can maintain it, it's easy to read, look" :)

10:31 chouser: Kjellski: heh, no worries. I've tended to bail on languages pretty quickly in the past, but rhickey got his hooks into me.

10:32 cemerick: magnet: that only matters if you need to go hire lots and lots of programmers. Warm bodies in abundance isn't necessarily an objective.

10:32 magnet: Kjellski, a more elegant weapon for a more civilized age?

10:32 from*

10:32 _ato: mmm.. and if you hire good programmers they should be able to pick up anything pretty easily

10:32 Kjellski: magnet : Oh please, got the link? I´ve searched for this but couldn´t find it again...

10:32 Chousuke: It's funny how people always focus on the parentheses with lisp syntax.

10:33 they just move around a bit. why does that matter so much? :(

10:33 chouser: Chousuke: since you asked

10:33 ...I'll tell you why it matters.

10:33 Kjellski: Chousuke : That´s just an "insider" from xkcd... ^^ nevermind

10:33 magnet: cemerick, depends on the shop you work at. Here it's Java only, and earlier a colleague came into my office asking for "the Scala guy" .. I have hope for a move to Scala, but I wouldn't dare dream to Clojure (even if I'd enjoy it)

10:34 Kjellski, the xkcd link?

10:34 Kjellski: magnet : yap

10:34 chouser: in C-like languages, foo(...) always means "call foo" or possibly use a builtin syntax thing called foo

10:34 raek: http://xkcd.com/297/

10:34 Kjellski: raek: thanks!

10:34 jdirks: Also for os clojure/lisp noobs it would be nice if the API page would contain (or a link to) a minimal example for every function with its intended use.

10:35 chouser: in C-like languages, the only other way parens are used are for grouping and syntactially it's clear they're not calling anything.

10:35 Kjellski: jdirks: : That´s definitively signed from me.

10:35 cemerick: magnet: right, that was mostly my point -- it's very, very hard to determine what's "best" w.r.t. language choice, because circumstances and premises vary so much.

10:35 Chousuke: chouser: hmm, I guess that makes sense. in Lisp you have parens everywhere so I suppose it looks messy to the uninitiated.

10:36 raek: you can see that strip on several office doors at the Institution of Computer Science here at Linköping University

10:36 Chousuke: chouser: I think Clojure suffers a lot less from that problem than CL or Scheme do, though. :)

10:36 chouser: In lisps (foo) could mean just about anything. I could be invoking a function or special form, or it could be deep in a nested form and just be a symbol in a list, or (in non-Clojure) it could be declaring a local named foo or be a special arg to a macro or ... who knows what!

10:37 Chousuke: yes, less. But it can still mean a fn or method def (in fn, letfn, proxy and now defclass and deftype) or a friggin' group of test cases in 'case'

10:38 Chousuke: I must say I like the scheme syntax for function definition, even though it has this "confusing" use of parens... (define (foo x y) ...) just makes sense.

10:38 cemerick: chouser: you don't like the parens in case, eh? :-)

10:39 chouser: cemerick: how'd you guess?

10:39 _ato: I don't have much of a lisp background (came from c, python, ruby etc) and I found Clojure a bit easier to read than other lisps because of the vector-syntax like (defn foo [a b c] whatever), makes things stand out more.

10:39 chouser: _ato: exactly. me too.

10:39 Chousuke: chouser: with fn, proxy, defclass/deftype I can forgive it because they all use it in a similar way (method/function definition)

10:40 Kjellski: I love the example from Stuarts book, where he showed the (.. ) macro just producing less parens than native java itself... that´s where I lost my fears about them I think...

10:40 chouser: Kjellski: ah, that's good to hear.

10:42 Chousuke: so Rich decided on lists for case syntax?

10:42 Kjellski: chouser: The problem for me was, the combination of different semantics for parens and exactly same looking data structure in "old" lisps... just like _ato said.

10:43 Chousuke: with Scheme you can actually use [] and {} interchangeably with ()

10:43 waste of good characters :P

10:43 chouser: Chousuke: that's what's in branch 'new' but perhaps it's not in stone yet.

10:43 cemerick: that *always* screws me up now

10:43 chouser: keep hope alive!

10:44 raek: which lisp has "superparens"?

10:44 like: ( ( ( ( ]

10:44 Kjellski: raek, that sounds pretty confusing...

10:44 Chousuke: but in elisp [...] actually is (vector ...)

10:47 djork: PLT Scheme uses [] interchangeably with ()

10:47 but I've never heard of superparens

10:47 sounds nice though

10:47 raek: I guess superparens were invented before highlight matching paren functionality of editors ;)

10:47 chouser: Franz Lisp used ] to close off all open parens

10:47 djork: heh heh

10:47 yeah

10:48 steiger: hm

10:48 super parens seems to be fun

10:50 Kjellski: I don´t get it, that makes only sense if they´re not used in a better way, like representing another data structure?

10:50 chouser: Kjellski: right

10:52 Kjellski: chouser: "Righty thenn..."

10:53 jdirks: Noob Question: I have a vector and for each element in it i need to call a function like (myfn index value) how should I do that?

10:53 AWizzArd: map

10:53 raek: does anyone know how to change coding system in slime?

10:53 AWizzArd: ,(map inc [10 20 30])

10:53 clojurebot: (11 21 31)

10:53 jdirks: I need to know the index in when calling the function

10:54 raek: on startup, slime says: (swank.swank/start-serve "/tmp/slime.24462" :encoding "iso-latin-1-unix")

10:54 AWizzArd: ,(use 'clojure.contrib.seq-utils)

10:54 clojurebot: java.lang.IllegalStateException: shuffle already refers to: #'sandbox/shuffle in namespace: sandbox

10:54 AWizzArd: ,indexed

10:54 clojurebot: #<seq_utils$indexed__697 clojure.contrib.seq_utils$indexed__697@ec0f07>

10:54 raek: I most definitely don't want to use latin1...

10:55 _ato: I think languages like Python are always going to have a small readability advantage over lisps as they read more like english, but lisps have huge benefits for writability -- besides the obvious macros, editor support (like eval hotkeys) works much better. Curly brace languages are neither really much more readable, nor writable, it's just everyone is used to them. :-P

10:55 AWizzArd: ,(map #(vector :index (first %) (inc (second %))) (indexed [10 20 30]))

10:55 clojurebot: ([:index 0 11] [:index 1 21] [:index 2 31])

10:55 rhickey: so, on the parens in case thing. If you want parens to always be 'calls', then how do you match lists? (case '(:a :b) (:a :b) "found" ...). parens still are list data designators, and the first of each clause is unevaluated data by definition (i.e. not a call)

10:56 _ato: A friend had previously tried to convert me (as a Python/Ruby user) to common lisp. I wrote a few programs and liked macros and the editor support, but I found the syntax difficult, but the clojure vector thing improved it enough to convert me.

10:57 chouser: rhickey: literal sets were mentioned as an option

10:57 jdz: _ato: which vector thing?

10:58 rhickey: so the desire to 'save parens for calls' eliminates their use here and elsewhere for data matching. The fact that vectors usually work for both has made that less of an issue, but it's a big deal to lose one of the 3 matching delimiter pairs

10:58 _ato: jdz: (let [x 1]) instead of (let ((x 1))) and (defn foo [a b] ...) instead of (define (foo a b) ...)

10:58 rhickey: chouser: that's still a possibility

10:58 Chousuke: _ato: and for lisps there's paredit :P

10:59 jdz: _ato: what's the difference?

10:59 rhickey: one problem is that almost everywhere else syntax calls for a logical set, a vector is used instead

10:59 using sets in case will beg the question as to why they aren't used in similar situations elsewhere

11:00 chouser: yes, it's a big deal to lose parens for other meanings, and futile to try to remove them completely -- you can always have deeply nested quoted structures or user macros that use literal lists as non-calls.

11:00 _ato: jdz: it makes it more obvious that [x 1] is not a function call, it's an assignment when you're reading the code

11:00 jdz: i personally have very mixed feelings about the property-list kind of specifying things (keys not being anything special)

11:00 Chousuke: _ato: Instead of manipulating lines of code, you manipulate *expressions*. It's simple, but... Once you learn it, there's no going back :P

11:00 jdz: _ato: not really. [x 1] might as vell be a vector acces.

11:01 and by property-list kind i mean undelimited pairs of things

11:01 chouser: And honestly it probably won't matter much to me personally anymore -- I'm in deep enough with the lispy syntax now to not be terribly confused by usages like for case. I can even read scheme somewhat more easily now.

11:01 jdz: so i prefer CL's style for both LET and COND

11:01 _ato: Chousuke: yeah, I'm a big paredit fan

11:02 Chousuke: I sometimes still open vim for quick edits of lisp code and it always feels silly to type the closing parentheses

11:02 chouser: But I do think it actually made a significant difference between the amount of effort it took to try to use CL vs. Clojure

11:03 rhickey: I will say that case was definitely a problem for me when I was learning CL, the whole unevaluated position thing, how symbols were used literally to match symbols, not referents. Of course, they don't even support composites as keys there

11:03 _ato: jdz: that's true. As a previous non-lisper though, it's just easier to adapt to for some reason. I'm used to assignments and method definitions being visually distinct. I never confused it with literal vector syntax for some reason

11:03 rhickey: chouser: don't get me wrong, Clojure definitely tries to use [] for non-calls as much as possible, and gets rid of lots of grouping

11:04 Chousuke: and there's always going to be a closing paren anyway, so the editor should just take care of it :P

11:04 jdz: _ato: yes, that's subjective.

11:04 chouser: rhickey: right. it's clear that was a goal and has been sufficient so far.

11:04 rhickey: 'proxy' and even multiple fn bodies are used rarely enough that beginners can look at a lot of code before having to deal with them.

11:05 rhickey: if [] and () were both supported as keys, would people expect case to differentiate by type?

11:05 because that would ruin case perf

11:05 Chousuke: chouser: and really, ([foo bar] stuff) is probably not going to look like a function call to a newbie anyway. they'll just go "what's that vector doing there?"

11:06 chouser: Chousuke: right

11:06 _ato: jdz: yeah, indeed, I'm sure it depends completely on what you're used to, but it gives Clojure a better chance at converting non-lispers, which is a good thing.

11:07 jdz: _ato: that's for sure -- non-lispers are used to syntax sugar :)

11:07 rhickey: well, the most important thing is that people kick the tires with deftype case etc. Please try 'new' branch everyone!

11:07 jdz: i'd say even addicted :)

11:07 Chousuke: [] and {} are not syntactic *sugar* though

11:08 nor is #{} (I always forget sets)

11:08 tomoj: how not?

11:08 jdz: Chousuke: depending on usage. in case of let and bindings they are.

11:08 *other bindings

11:08 but then, CL has vectors, too: #(1 2 3)

11:08 Chousuke: jdz: not really. for example, destructuring would be slower if lists were used instead of vectors

11:09 jdz: Chousuke: nah, implementation details.

11:09 Chousuke: they're *real* vectors, as syntax. not shortcuts for (vector foo bar)

11:09 that means that in your macro you can use nth on the vector and it's constant time.

11:09 jdz: #(1 2 3) is also a real vector, and not a shortcut.

11:10 but it is offtopic anyway

11:11 Chousuke: so you will be able to manipulate a vector if you do (somemacro #(foo bar))? and somemacro takes a single parameter :)

11:11 jdz: Chousuke: but of course

11:12 Chousuke: if foo and bar are bound, that is

11:12 Chousuke: why do they need to be bound? :/

11:12 jdz: Chousuke: same reason as in Clojure, they would be treated as variables

11:13 Chousuke: oh wait a second.

11:13 _ato: hehe so Clojure is like a nicotine patch for syntax sugar... weaning you off overcomplicated, sugared syntax but still with enough variety to prevent withdrawl symptoms. :-P

11:13 Chousuke: if #() were just a reader expansion to (vector foo bar) you'd get a list for manipulation in your somemacro

11:13 jdz: Chousuke: it's a macro, so yes, you'd get a vector of 2 elements

11:14 Chousuke: symbol FOO and symbol BAR

11:14 Chousuke: right.

11:14 probably no-one uses vectors for macro syntax in CL though.

11:14 #() looks a bit ugly. :P

11:15 jdz: Chousuke: well, yes it does. that's why i don't like it in Clojure :P

11:15 but in CL it is used very rarely

11:15 rhickey: Clojure: (let [a 1 b 2 c 3] [a b c]) CL: (let ((a 1) (b 2) (c 3)) `#(,a ,b ,c))

11:16 cemerick: Chousuke: really? I quite like it. What would a good alternative be, in a parallel universe?

11:16 Chousuke: cemerick: I don't think there's anything better

11:16 _ato: in a parallel universe keyboards would have a lambda character instead of # :p

11:16 Chousuke: I think #() fits quick lambdas better than vectors, anyway

11:16 jdz: rhickey: not really. (let ((a 1) (b 2) (c 3)) #(a b c))

11:17 djork: I appreciate the fact that I can use evenly-counted vectors instead of (() () ())

11:17 chouser: jdz: nope

11:17 rhickey: jdx, no #(a b c) is a vector of 3 symbols, unevaluated

11:17 Chousuke: the # kind of says "make the next expression a function"

11:17 jdz: rhickey: ye, sorry. my CL is still swapping in ;)

11:17 steiger: _ato: in PLT Scheme, you can type the lambda character with CTRL+Z on their IDE

11:17 it works as syntactic sugar to the keyword lambda

11:18 i think

11:18 Chousuke: heh

11:18 tomoj: my emacs does that when I type lambda

11:18 Chousuke: yeah, mine too :P

11:18 tomoj: but no "lambda" in clojure anyway, and "fn" is short enough

11:18 rhickey: jdz: that example highlights the difference - vectors have interpretation as syntax during evaluation in Clojure, in CL they are just a reader thing, embeds a vector in your code

11:18 steiger: fn is fine ;)

11:19 jdz: rhickey: yes, differences are ok, as long as there are reasons behind them. keep up the wonderful job you're doing :)

11:20 i did not want to drag CL in here, so, back to the scheduled regular Clojure discussions.

11:21 Chousuke: I wonder what it would take for Clojure to support continuations :/

11:22 steiger: is github down or something? what happened to richhickey/clojure ?

11:22 Chousuke: :o

11:23 _ato: yeah github's offline for maintainance

11:23 Chousuke: I wonder if they're finally going to make it faster.

11:23 steiger: oh yeah, i read it on the main page

11:23 _ato: "We are experiencing some heavy load on the frontends caused by a vast number of processes waiting for responses from the backend. On it."

11:24 Chousuke: fortunately github is not central to development :D

11:25 _ato: steiger: you can still clone with: (defn readline-seq [rdr] (lazy-seq (cons (.readLine rdr) (readline-seq rdr))))

11:25 gah

11:25 wrong paste

11:25 I meant: git clone git://github.com/richhickey/clojure.git

11:25 steiger: _ato: i was wondering how the hell that would clone a git repo ;P

11:26 _ato: well... I guess if you redefine defn in a really strange way... :p

11:34 chouser: ,(macroexpand '`[1 2 3])

11:34 clojurebot: (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list 1) (clojure.core/list 2) (clojure.core/list 3))))

11:36 Chousuke: why does it include the seq call? :/

11:36 _ato: wow.. that's weird

11:37 ,(macroexpand ``[1 2 3])

11:37 clojurebot: (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list 1) (clojure.core/list 2) (clojure.core/list 3))))

11:37 _ato: ,(macroexpand `'[1 2 3])

11:37 clojurebot: (quote [1 2 3])

11:38 Chousuke: syntax-quote is completely read-time so the macroexpansion is weird :)

11:38 djork: interesting

11:38 chouser: I look forward to that changing.

11:38 Chousuke: but that's what it has to expand to, because it has to build the structure at runtime.

11:39 so even a macro implementation will eventually produce something like that.

11:39 chouser: my macro sq already works but it probably has some corner cases. :/

11:39 chouser: Chousuke: hm, good point.

11:39 _ato: ah right

11:39 it's because of splicing

11:39 chouser: the concat is to leave room for splicing

11:39 right

11:40 Chousuke: what I don't get is why there's teh seq after the concat

11:42 _ato: ret = RT.list(APPLY, VECTOR, RT.list(SEQ, RT.cons(CONCAT, sqExpandList(((IPersistentVector) form).seq()))));

11:42 hmm

11:43 Chousuke: heh.

11:43 chouser: It's a java macro!

11:43 Chousuke: a clojure reader macro written in Java :P

11:44 chouser: all the clojure reader macros are written in java

11:44 Chousuke: well, yeah.

11:44 hmm

11:44 I think I'll try running the contrib test suite with my sq-macro-clojrue

11:44 clojure

11:45 _ato: although you think the reader could just expand it to (backquote whatever) and then you could define it in clojure

11:45 chouser: so concat always returns a seq anyway. so (seq (concat ...)) can only be to get nil on empty, right?

11:45 _ato: yes, that's the plan

11:45 _ato: yeah but (apply vector '()) and (apply vector nil) behave the same

11:46 maybe it's from pre new lazy

11:46 or sometime even earlier when things behaved differently

11:52 avital: Hi. To whom do I report broken links on http://richhickey.github.com/clojure-contrib/monads-api.html#monads/writer-m?

11:53 chouser: avital: I think github is just having problems at the moment.

11:55 avital: Ok cool. And for another question, can anyone point me to an example of using the update-state function from the clojure-contrib monads library? I feel like if I only see one working example it may all fall into place.

12:06 AWizzArd: avital: look at fnparse

12:06 avital: AWizzArd: Thanks, GitHub is broken now, I'll take a look later.

12:06 AWizzArd: at github, http://github.com/joshua-choi but also down right now

12:07 avital: And do we all agree that monads are probably the craziest and most amazing thing in the world or something?

12:07 chouser: are they amazing?

12:08 I need something to sell me monads the way "on lisp" sold macros.

12:09 _ato: yeah, to me they just seem to overcomplicate things without any major benefits

12:09 avital: chouser: I'm going to try to make this thing that transforms all code into monad comprehension that allows you to attach arbitrary monad transformations thus allowing logging, profiling, exception handling and millions of other things just by adding one keyword each.

12:10 rhickey: I'm thinking about requiring . before method names in reify/defclass/deftype

12:10 avital: No really. Monads are probably the most important thing or something.

12:10 chouser: rhickey: in the syntax for defining the method?

12:11 rhickey: because right now (deftype/reify .... (seq [] (seq "foo"))) the second seq is core/seq

12:11 chouser: yes: (.seq [] (seq "foo"))

12:11 srader: I've done a bit of micro-benchmarking with deftype/defclass. (time (dotimes [_ 10000000] (:age p))), where p is either deftype-obj, defclass-obj, PersistentStructMap, or PersistentArrayMap. I get PersistentStructMap slower (2x) than deftype-obj, which is slower (1.5x) than PersistentArrayMap, which is slower (4x) than defclass-obj.

12:11 defclass is very fast!

12:11 chouser: rhickey: I think that sounds nice.

12:12 hiredman: avital: http://tinyurl.com/ylk8lys

12:12 _ato: rhickey: regarding " *

12:12 avital: hiredman: AMAZING

12:12 _ato: Universal field identifiers" ie the RDF namespacing of methods

12:13 can't you just namespace qualify them?

12:13 or is the idea to try to prevent tying them to any one package so you could have multiple implementations?

12:15 rhickey: _ato: right, namespaces would tie them to a lib, but you usually just want tiny field name + more universal name that might cross libs/apps

12:17 rhickey: reify/deftypes do not really have full class scope, only the fields have environment bindings, so this might clarify

12:17 er, chouser

12:17 ^^

12:19 qed: hello ladies and germs -- Anyone know of a good way to do syntax hilighting on clojure code for a website?

12:19 I'm using rails right now -- didn't know if there was anything already out there...

12:20 chouser: rhickey: oh, can you refer to fields as if they were locals in method bodies?

12:21 AWizzArd: funny :)

12:26 _ato: aah right.. it's too late at night.. it's universal *field* identifiers. I read that as *method* for some reason.

12:27 AWizzArd: too late in the night? East Russia?

12:27 leafw: qed: I am only aware of lisp javascript syntax highlighters.

12:28 _ato: AWizzArd: Australia, it's 3:30 am

12:28 tomoj: github can highlight clojure right?

12:29 so I guess that means pygments can do it?

12:29 and pygments has a ruby wrapper

12:29 qed: ^

12:30 yes, clojure is on pygments' language list

12:31 kefka: ,(class (hash-map))

12:31 clojurebot: clojure.lang.PersistentArrayMap

12:32 _ato: kefka: array maps are used as an optimisation for small hash maps

12:32 kefka: I know, but there's a problem.

12:33 I'm working with transient collections.

12:33 If you're using assoc!, TransientArrayMap is worthless (at least according to spec)

12:34 because when there are more than 8 keys, the TransientArrayMap is full; assoc! returns the TransientHashMap, but the old array-map sticks around.

12:34 ,(class (hash-map :a 1))

12:34 clojurebot: clojure.lang.PersistentHashMap

12:34 chouser: once you've used 'assoc!' you shouldn't be touching the old collection anyway

12:35 kefka: chouser: you should be using the one returned, I assume?

12:35 chouser: kefka: right. Otherwise you're guilty of "bashing in place" and lots of things will break.

12:36 (doseq [...] (assoc! ...)) is bad, for example.

12:36 kefka: Same rule for conj?

12:36 chouser: even with transients you should structure your code as if they were immutable, using the new collections, throwing away the old ones.

12:36 _ato: when doing transients the simple rule is you should be able to remove (transient) (persistent!) and replace assoc! with assoc and the code should still work exactly the same

12:36 yeah

12:37 kefka: So the purpose of transients is just a performance optimization, then?

12:37 chouser: yes, that's it.

12:37 _ato: yes

12:37 clojurebot: http://clojure.org/transients

12:37 chouser: if you want mutable collections ...which you don't! :-)... Java provides several.

12:38 Chousuke: hmmh

12:39 ,`(let [foo# 5] `(test ~'foo#))

12:39 clojurebot: (clojure.core/let [foo__5499__auto__ 5] (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/test)) (clojure.core/list (quote foo__5499__auto__)))))

12:40 Chousuke: my sq-macro doesn't handle that properly :(

12:40 kefka: chouser, _ato: Thanks

12:40 Chousuke: ,`(let [foo# 5] `(test ~foo#))

12:40 clojurebot: (clojure.core/let [foo__5503__auto__ 5] (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/test)) (clojure.core/list foo__5503__auto__))))

12:40 kefka: ,(doc assoc!)

12:40 clojurebot: "([coll key val] [coll key val & kvs]); When applied to a transient map, adds mapping of key(s) to val(s). When applied to a transient vector, sets the val at index. Note - index must be <= (count vector). Returns coll."

12:41 Chousuke: hm

12:41 ,`(x# `[x#] `[x#])

12:41 clojurebot: (x__5521__auto__ (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list (quote sandbox/x__5519__auto__))))) (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list (quote sandbox/x__5520__auto__))))))

12:42 Chousuke: hm :/

12:43 I'm not sure how to implement this

12:43 AWizzArd: what do you want to do?

12:44 Chousuke: make my syntax-quote macro work :P

12:45 it doesn't handle nested syntax-quotes with unquoting quite right.

12:47 ,`(x# `[~x#] `[x#])

12:47 clojurebot: (x__5526__auto__ (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list x__5526__auto__)))) (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list (quote sandbox/x__5525__auto__))))))

12:48 chouser: only a problem when autogensym is used?

12:48 Chousuke: ,`(x# `[~x# `~x#])

12:48 clojurebot: (x__5531__auto__ (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list x__5531__auto__) (clojure.core/list (quote sandbox/x__5530__auto__))))))

12:49 Chousuke: as far as I can tell.

12:49 but that's just evil now.

12:50 ,`(x# `[~x# y# `~y#])

12:50 clojurebot: (x__5536__auto__ (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list x__5536__auto__) (clojure.core/list (quote sandbox/y__5535__auto__)) (clojure.core/list (quote sandbox/y__5535__auto__))))))

12:51 Chousuke: hmmh.

12:52 ,`(x# `[~x# x# `~x#])

12:52 clojurebot: (x__5541__auto__ (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list x__5541__auto__) (clojure.core/list (quote sandbox/x__5540__auto__)) (clojure.core/list (quote sandbox/x__5540__auto__))))))

12:56 notallama: i was looking at comp, juxt, and partial. why do they have several different arities, rather than just the general "& rest" ones? is it more efficient that way?

12:57 Chousuke: maybe easier.

12:57 because you don't have to manually extract the parameters.

13:01 I think Clojure's syntax-quote is taking advantage of the fact that it's read-time :(

13:01 hiredman: clojurebot: syntax-quote is very hairy

13:01 clojurebot: Ik begrijp

13:05 Chousuke: yeah... the syntax-quotes are actually expanded inside-out, which is why it works.

13:08 hm.

13:09 _ato: Chousuke: I've got no idea how you're implementing it, but can't you make your macro do the same? Perhaps by explicitly macro-expanding everyting inside or something?

13:09 Chousuke: right. that's what my "hm." above was.

13:09 _ato: hehe :)

13:10 rhickey: chouser: yes, fields are in the local environment

13:22 Chousuke: oh wow. it actually works.

13:24 and it succesfully compiled contrib

13:24 rhickey: reify is alive! .methodnames, more docs : http://github.com/richhickey/clojure/commit/9c3e97a85c042d2c3f276f0c1e0d270db35553aa

13:33 dakrone: is there a refactormycode-type site that supports Clojure?

13:38 chouser: quite a week for branch 'new'!

13:38 clojurebot: for is not a loop

13:38 djork: dakrone: that seems like just another pastebin

13:38 I just use gist usually

13:39 drewr: limit on number of case clauses? http://gist.github.com/222567

13:40 dakrone: djork: well, I meant something like "this is my clojure code, please tell me how I can make it better/less java-ish"

13:40 djork: that's what this room is for :)

13:40 I think you'll find most of the programmers online who are able to help you with that right here.

13:41 dakrone: alright then, I'll post it here :)

13:41 chouser: or on the google group

13:41 dakrone: how does this look? http://pastie.org/677017

13:42 just kinda looking for feedback as in "don't do this" or "do this instead"

13:42 mikehinchey: rhickey: I like the .methodname change

13:42 rhickey: I have iterator-seq working with proxy (no java), I'm trying with reify

13:43 chouser: dakrone: if BLIP_SUBMITTED is a field, you don't need parens around it

13:43 use (inc x) instead of (+ 1 x)

13:43 djork: ah the geek favorite... die rolling

13:44 dakrone: chouser: okay, will do, thanks

13:44 chouser: no need for re-pattern around #""

13:44 you might consider using destructuring in calculate-rolls

13:46 dakrone: chouser: so something like (let [[text dice sides] txt] ...) ?

13:47 chouser: instead of (if-not (= (re-find ...) nil) foo) you can say (when (re-find ...) foo)

13:48 dakrone: or just (defn cr [[text dice sides]] ...) not sure if you'll like the results since you'd still have to process dice and sides.

13:48 dakrone: chouser: is it similar to Ruby where anything other than 'false' or 'nil' is true?

13:48 chouser: dakrone: exactly

13:48 dakrone: okay, that helps

13:49 chouser: dakrone: looks good! nice clean code, good use of high-order functions, no state

13:50 dakrone: chouser: thanks! I appreciate the feedback very much

13:51 chouser: dakrone: you have it actually working on wave?

13:52 dakrone: chouser: yep, works great

13:52 chouser: very cool. I just haven't taken the time yet to do anything with wave.

13:52 dakrone: chouser: so far building robots is the best part of Wave :)

14:00 djork: and in clojure, no less

14:03 drewr: where's a current example of deftype?

14:03 the Datatypes wiki seems out of date

14:04 chouser: drewr: yeah -- by at least 2 or 3 days.

14:04 you're probably best of looking at the wiki for concepts and the deftype docstring for syntax.

14:04 GenericUser0: Hello

14:04 rhickey: drewr: docstring has gotten a lot better - feedback welcome

14:05 now that reify is in, I'll doc all three (reify/deftype/defclass) on the wiki soon

14:05 GenericUser0: What is the idiomatic way of performing a zip of several collections in clojure? I can't seem to find a zip function in the API.

14:06 chouser: GenericUser0: 'map' takes multiple collection args

14:06 rhickey: so you can just map vector

14:07 GenericUser0: Ah, ok. Thanks.

14:08 rhickey: ,(map vector [1 2 3] [:a :b :c] [:d :e :f])

14:08 clojurebot: ([1 :a :d] [2 :b :e] [3 :c :f])

14:11 froog: what is reify?

14:12 rhickey: froog: like proxy but: faster, limited to interfaces

14:13 (seq (reify [clojure.lang.Seqable] (.seq [] (list 1 2 3)))) -> (1 2 3)

14:15 the method bodies are true method bodies, yet close over local scope, calls have no lookup and no indirection to fns, much faster construction

14:16 froog: rhickey: great, thanks, I see now

14:20 djork: can I just gush for a second and say how freaking brilliant the lazy-seq facilities of clojure are?

14:20 the fact that take is lazy just blows my mind

14:20 (take 1 (take 10 x)) for example

14:22 not that I'd do that, I just have a function that returns (take n ...) and I just wanted the first one, so I took one and it was faster!

14:23 ok, </fanboyMode>

14:27 Chousuke: arr, recursively macroexpanding syntax-quote breaks :(

14:28 I wonder if I could just cheat and limit the depth... and then hope no-one has `[x# `````[~x#]]

14:28 drewr: so is my case clauses benchmark retarded?

14:28 Chousuke: ,`[x# `````[~x#]]

14:28 clojurebot: java.lang.ClassFormatError: Invalid method Code length 66815 in class file sandbox$eval__5550

14:28 Chousuke: :D

14:29 okay, looks like I should be fine.

14:29 drewr: since the dispatch is supposed to be constant-time I thought I'd see for myself

14:29 Chousuke: ,`[x# ```[~x#]]

14:29 clojurebot: [x__5554__auto__ (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/seq)) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/concat)) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/list)) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote quote)) (clojure.core/list (qu

14:34 twbray: ,(re-seq #".*" "foo\nbar\n")

14:34 clojurebot: ("foo" "" "bar" "" "")

14:34 * twbray is puzzled

14:35 chouser: . doesn't match newline

14:35 twbray: Right, but would've expected ("foo" "bar" "")

14:35 ,(re-seq #".*" "foo\nbar")

14:35 clojurebot: ("foo" "" "bar" "")

14:37 chouser: * is zero or more

14:37 ,(re-seq #".+" "foo\nbar")

14:37 clojurebot: ("foo" "bar")

14:38 twbray: Yeah, but if I'm trying to break "foo\nbar\n" into line fragments, I want 3 fragments, one empty. So .* is really what I want not .+

14:38 * twbray should write some java.util.regex code to find out where the disconnect is

14:39 * twbray or go see what perl does :)

14:39 chouser: perl does the same

14:40 twbray: Sigh. OK.

14:40 chouser: perl -e'$x="foo\nbar\n"; $x=~s/.*/[$&]/g; print "$x\n"' ==> [foo][]\n[bar][]\n

14:42 ,(re-seq #"(?m)^.*$" "foo\nbar\n\n")

14:42 clojurebot: ("foo" "bar" "")

14:42 twbray: Wow, thanks

14:42 technomancy: ,(doc line-seq)

14:42 clojurebot: "([rdr]); Returns the lines of text from rdr as a lazy sequence of strings. rdr must implement java.io.BufferedReader."

14:43 twbray: (re-seq #"(?m)^.*$" "foo\nbar\n")

14:43 hiredman: so arrayseqs are apparently mutable...

14:43 twbray: ,(re-seq #"(?m)^.*$" "foo\nbar\n\n")

14:43 clojurebot: ("foo" "bar" "")

14:43 twbray: ,(re-seq #"(?m)^.*$" "foo\nbar\n")

14:43 clojurebot: ("foo" "bar")

14:43 chouser: hiredman: yeah, if you still have access to the array

14:44 hiredman: chouser: :(

14:44 chouser: twbray: that's the normal meaning of \n -- as a line terminator not a line separator

14:44 twbray: at least I assume that's why ^ doesn't match after the last \n

14:45 twbray: Yeah, got a java.nio.CharBuffer I want to split into \n-separated chunks and it really matters if there's a trailing \n because that means an empty chunk

14:46 notallama: you can put flags on patterns in java to change the behavior of /n and such.

14:46 chouser: this is rather surprising:

14:46 ,(seq (.split #"\n" "foo\nbar\n\n\n\n"))

14:46 clojurebot: ("foo" "bar")

14:46 twbray: Ah, flags, good idea

14:48 GenericUser0: Why does something like (apply (partial < 5) 6) fail?

14:48 hiredman: apply expects the last arg to be a seq

14:48 chouser: apply require its last arg to be a collection

14:48 GenericUser0: (sorry if I get disconnected, my anti-virus is being annoying today, and seems to want to kill anything associated with IRC...)

14:48 hiredman: ,(apply (partial < 5) 6 nil)

14:48 clojurebot: true

14:48 hiredman: ,(apply (partial < 5) 6 '())

14:48 clojurebot: true

14:49 hiredman: ,(apply (partial < 5) 6 [])

14:49 clojurebot: true

14:49 hiredman: etc

14:49 twbray: Where do regex flags like /s and so on in #"" regexes?

14:50 notallama: twbray: you might have to dip into java to do it, and use the horrible java regex syntax.

14:50 twbray: notallama: Yeah, that may be it

14:50 chouser: ,(take-nth 2 (re-seq #".*" "foo\nbar\n"))

14:50 clojurebot: ("foo" "bar" "")

14:51 hiredman: java regex flags are generally something like (?i) at the fron of the regex

14:51 chouser: I used the m flag earlier: #"(?m)..."

14:51 hiredman: ,(re-find #"(?i)foo" "FOO")

14:51 clojurebot: "FOO"

14:51 chouser: twbray: but anyway, there's your solution take-nth + re-seq

14:51 twbray: Thanks

15:00 krumholt: hi anyone knows a good book about functional software architecture? i want something similar to the hundreds of books about object-oriented analysis and design. just for functional programming

15:00 duncanm: dum de dum

15:01 i have this little bit of Java code, I can't quite think of a way to write it in idiomatic clojure - http://gist.github.com/222629

15:01 chouser: I wonder if the various functional languages are similar enough for a general text to be useful.

15:02 duncanm: hey chouser

15:02 while ((count = input.read (data, 0, SIZE)) != -1) { output.write (data, 0, count); }

15:03 loops like that, i don't know what to do, should I go back to using set!, should i use refs?

15:03 oh, maybe loop/recur?

15:04 krumholt: chouser, i mean like a book of fundamentals for application development with functional programing languages

15:04 chouser: loop/recur would work, but it always does.

15:04 duncanm: but repeatedly would probably work here too

15:07 duncanm: untested: (let [data (make-array Byte/TYPE data-block-size)] (doseq [c (repeatedly #(.read input data 0 data-block-size)) :while (> c -1)] (.write output data 0 c)))

15:07 loop/recur might be every bit as good

15:17 yacin: agreed

15:17 whoops

15:17 wrong chan

15:30 falkor: I was looking at clojure.contrib.graph and noticed that it is mainly directed graphs only, right? Things like undirected graphs, edges with weights.... not there... Or am I failing to see something?

15:31 tomoj: well you could always just have two edges between each node

15:31 I dunno about edge weights.. I'm doing stuff with edge weights on directed graphs now and decided to just start from scratch

15:32 falkor: tomoj: that would be a cycle :( Plus, how to do weigths?

15:32 I am mainly working with weigthed trees... BTW, I suppose you know of JGraphT and JGraph... you might find it helpful....

15:37 tomoj: falkor: yeah been lookin at JGraph but I don't have my network library workin quite well enough yet to use it

15:38 chouser: rhickey: so if I want the speed of direct field access but don't want AOT or a named class, that still points me to reify?

15:38 falkor: tomoj: suggestion, also check JGraphT, in case you have not done it. You might find it interesting

15:40 tomoj: falkor: thanks

15:40 not interested in mutable graphs, though

15:40 ;)

16:06 rhickey: chouser: no, reify and deftype have the same perf - both give you direct field access *within* methods, reify gives you no access outside, and deftype gives you :field access outside. Both compile method bodies to true methods etc. It's all the exact same code for reify/deftype/defclass, it's just with defclass you end up with a named class which lets you access the fields direct *outside* of methods

16:07 chouser: ah... right right.

16:08 rhickey: one thing that is not there is any notion of private helper methods

16:09 chouser: with immutable objects the dangers of visible helper functions are pretty low. I guess can be confusing for users to see them.

16:12 rhickey: right, but external helpers can't have same perf as helper methods, at least for deftypes

16:13 the problem with helper methods is making them visible to the compiler's host interop infrastructure, the stub class hack would need more work

16:17 GenericUser0: Is there a program that will let me expand the stages of a function call so I can see where it's failing?

16:18 I have a lot of somewhat complicated functions that are returning closures, and they are composable... so debugging it is rather challenging at the moment.

16:18 (I'm doing a sort of pattern-matching over s-expressions)

16:18 suggestions?

16:20 chouser: GenericUser0: do you mean besides stack traces?

16:20 GenericUser0: Stack traces aren't working very well for me at the moment

16:21 All I get is something like

16:21 java.lang.IllegalArgumentException: Wrong number of args passed to: user$lit--7233$fn (NO_SOURCE_FILE:0)

16:21 I think I've mentioned this before.

16:22 but I'm not sure what happened to my logs.

16:22 chouser: (.printStackTrace *e)

16:22 that should give you the full trace. Each line of the trace should name a filename and linenumber.

16:23 GenericUser0: I get nil O_o

16:23 Maybe I'm catching it wrong hang on a sec

16:24 chouser: well, *e is defined at the plain repl for exceptions that bubble all the way out there

16:25 GenericUser0: Argh. Screw McAfee >.<

16:25 keeps killing my IRC connection, and automatically resetting the firewall rules

16:26 Yeah, I just nil.

16:26 chouser: GenericUser0: are you at a plain terminal repl?

16:27 GenericUser0: I'm doing basically: (try <my expression> (catch Exception e (.printStackTrace e)))

16:27 I'm in Clojure Box's emacs

16:27 chouser: oh. hm. that should work

16:27 without the try/catch slime is supposed to help you out I think, but I don't do slime

16:28 GenericUser0: Oh... I see it now. It's hidden.

16:28 ...still not especially helpful though, unfortunately :/

16:28 It's being raised by clojure.lang.Compiler.eval

16:29 durka42: try clojure.stacktrace/print-cause-trace

16:29 dakrone: can someone tell me what I'm doing wrong with this xml parsing? http://pastebin.com/d4b960346

16:30 GenericUser0: In the catch from before, instead of .printStackTrace ?

16:30 durka42: GenericUser0: yes

16:30 it chains through Exception/getCause or whatever it is called

16:31 dakrone: what are the symptoms?

16:31 GenericUser0: ClassNotFoundException: clojure.stacktrace

16:31 durka42: meh, isn't that what it's called

16:31 ,(use 'clojure.stacktrace)

16:31 clojurebot: nil

16:31 dakrone: durka42: it returns (), instead of the text inside the fcttext XML element

16:31 durka42: ,(print-cause-trace (throw (Exception. "blah")))

16:31 clojurebot: java.lang.Exception: blah

16:32 GenericUser0: I don't seem to have that in clojure box for some reason. Huh.

16:32 durka42: ,(print-cause-trace (Exception. "blah"))

16:32 clojurebot: java.lang.Exception: blah at sandbox/eval (NO_SOURCE_FILE:-1) clojure.lang.Compiler.eval (Compiler.java:4623) clojure.core/eval (core.clj:1966) hiredman.sandbox/cond_eval (sandbox.clj:72) hiredman.sandbox/eval_in_box_helper (sandbox.clj:108) hiredman.sandbox$eval_in_box__112$thunk__117.invoke (sandbox.clj:123) hiredman.sandbox/wrap_exceptions (sandbox.clj:32) hiredman.sandbox/wrap_exceptions (sandbox.clj:28) hiredman.sand

16:32 durka42: GenericUser0: if you have an oldish version of clojure, it's clojure.contrib.stacktrace

16:32 GenericUser0: Is it very new?

16:32 chouser: dakrone: :forcastday -> :forecastday ?

16:32 GenericUser0: Ah

16:32 now it works. Thanks

16:33 dakrone: chouser: totally missed that typo, unfortunately it still only returns ()

16:33 chouser: xml-> turns out to be quite fragile like this. Not sure how to fix it. :-/

16:34 dakrone: chouser: is there a recommended way? searching the internet reveals a number of different methods, but no real exhaustive examples

16:35 chouser: as in alternatives to zip-filter?

16:35 dakrone: chouser: that or the recommended xml-parsing way

16:36 chouser: I dunno. I wrote zip-filter exactly for scenarios like this, but each time I use it spend some amount of time fiddling with filters that just return empty seqs.

16:36 I used enlive once, but for XML you have to hack around it a bit, and I haven't used it enough to know if it's any less fragile in this way.

16:37 dakrone: so, should I parse it with java libraries instead of in a clojure way?

16:39 chouser: dakrone: try leaving off the initial :forecast

16:40 (xml-> feed :txt_forecast :forecastday :fcttext text)

16:41 dakrone: chouser: yep, that fixed it

16:44 dakrone_: chouser: how does the (text ...) call know that the content is inside a :content tag?

16:44 chouser: text is c.c.zip-filter.xml/text, specific to the maps produced by c.xml/parse

16:45 dakrone_: oh okay

16:46 makes much more sense now

16:51 chouser: rhickey: when there are collections that support primitives and/or fns with primitive args, with the interfaces support all types but throw runtime errors on incorrect types, or will there be multiple interfaces (presumably with almost nothing in common)

16:51 rhickey: I ask because I'm thinking about primitive measure/reduce for finger-tree

16:53 rhickey: chouser: don't know yet - certainly they must support the object interfaces for compatibility. There may be parallel interfaces for long/double, or methods next to existing (although not type-overloaded - new type-qualified names, e.g. valAtLong)

16:53 chouser: ok

16:56 Right now I have [(fn measure ...) (fn reducer ...) init-val]. So I'm thinking those could be methods of a reify with IMonoid

16:56 rhickey: I do know I want to restrict it to long/double at the interface, i.e. that is all that will be supported by fn (eventually).

16:56 chouser: yep, and that makes sense to me.

16:58 It's hard to see how else to allow primitives for my IMonoid methods without ILongMonoid and IDoubleMonoid, and then not have those either checked at runtime or bubble all the way up to IFingerTreeMeasureLong and IFingerTreeMeasureDouble

16:58 well, anyway, gotta run. Thanks for your answers.

17:20 kanak: Hi. Can someone tell me whether cons is lazy by default, or if it is lazy only when wrapped around lazy-seq?

17:20 hiredman: lazy-seq

17:21 kanak: thank you.

17:21 is there a way for me to check if something is a lazy seq?

17:23 digash`: ,(instance? clojure.lang.LazySeq (lazy-seq []))

17:23 clojurebot: true

17:24 kanak: thank you digash.

17:27 Can someone tell me when i should prefer cons to conj (or vice versa)?

17:29 cemerick: kanak: can only "add" to a list (or nil). conj will "add" to any collection.

17:30 rhickey: kanak: conj in almost all cases other than when building a lazy sequence using the general form (cons first-item (recursive-call to build rest))

17:31 kanak: thank you rhickey and cemerick.

17:33 rhickey: kanak: sure

17:40 twbray: I have a big list and I want to map a function onto it, but the function is mostly (send ), no useful result, is there an equivalent of (map that doesn't bother returning the new list?

17:41 kanak: twbray: doseq?

17:41 * twbray realises this is probably premature optimization

17:41 rhickey: twbray: what map actually returns is lazy (the list doesn't yet exist), you can call dorun on that and it will walk it (for effects), discarding the result

17:41 but sometimes that is better expressed with doseq

17:41 twbray: Oh cool. Thanks

17:42 * twbray wanders off to learn doseq

17:46 technomancy: it's not an optimization if you use doseq to communicate intention... using map on some level implies you're interested in the return value

18:02 st3fan: hm how do i filter on a map?

18:03 filter on a map seems to return a vector instead of a map

18:03 Chousuke: you can treat it as a seq of [k v] vectors

18:03 st3fan: hmm

18:03 i basically want to filter out some key/value pairs as part of a swap! operation

18:04 Chousuke: so (into {} (filter (fn [[k v]] ...) amap)

18:04 technomancy: st3fan: you can also reduce conditionally

18:04 into is probably clearer though

18:04 st3fan: i'll give it a try

18:06 got it!

18:16 rhickey: doc update in progress: https://www.assembla.com/wiki/show/clojure/Datatypes

18:27 kanak: Is the idiomatic way to do letrec (scheme)/lables (cl) in clojure just using a private function using defn- ?

18:31 rhickey: ,(doc letfn)

18:31 clojurebot: "([fnspecs & body]); Takes a vector of function specs and a body, and generates a set of bindings of functions to their names. All of the names are available in all of the definitions of the functions, as well as the body. fnspec ==> (fname [params*] exprs) or (fname ([params*] exprs)+)"

18:32 rhickey: kanak: letfn ^^

18:33 kanak: rhickey, thanks again :)

19:23 hmm. why does (seq? [1 2 3]) return a false?

19:25 Chousuke: kanak: a vector is not a seq by itself. You need to call seq on it to get a sequence view of it.

19:26 kanak: I see. So how do i test if something is a clojure sequence?

19:26 technomancy: kanak: iseq? tests if it implements the seq interface

19:26 or if it can "become" a seq

19:27 Chousuke: there actually is such a function now?

19:27 technomancy: erm; it's called something else

19:27 Chousuke: ,(seqable? "foo")

19:27 clojurebot: java.lang.Exception: Unable to resolve symbol: seqable? in this context

19:27 Chousuke: hmm

19:27 something likethat was in contrib

19:27 but nothing in core :/

19:28 * technomancy could also possibly be full of it

19:28 technomancy: wouldn't be the first time

19:28 kanak: contrib.core has seqable

19:29 gthompson: does sequential? do it?

19:31 kanak: sequential? gives the desired results but I wonder if using it in this sense is misusing it.

19:41 gthompson: I'm new to clojure so I don't know what the intended use of sequential? is? I just found it with autocomplete in slime ;)

19:48 kanak: gthompson: sequential? checks if the object implements Sequential, whereas I want to test if something implements Seqable (i.e. supports first, rest, and next). So i think like its just a coincidence that it gives the right answer right now :)

19:50 gthompson: a happy coincidence today is the road to a horrible bug tomorrow :)

19:50 kanak: my thoughts exactly :D

20:10 * terrycojones following @timbray into #clojure :-)

20:13 bitbckt: A little word-of-tweet goes a long way.

20:13 terrycojones: bitbckt: :-P

21:37 cemerick: whoa, since when is #clojure dead on a Friday night? :-P

21:38 Knekk: since everyone is attending halloween parties dressed up as Scala and Haskell

21:39 terrycojones: clojure doesn't need a costume to look scary :-)

21:39 * Knekk is personally dressing up as a clojure macro

21:40 * terrycojones is wondering if someone will rewrite emacs in clojure one of these days. would be nice.

21:41 _ato: terrycojones: http://dorophone.blogspot.com/2009/05/clojure-style-destructuring-binding-for.html

21:41 unfortunately elisp is too limited to be able to be morphed completely into clojure via macros :(

21:45 terrycojones: _ato: thanks!

21:45 chouser: terrycojones: it is inevitable that many will try. likely that most will fail.

21:46 maybe we'll be lucky and one wil succeed.

21:47 terrycojones: chouser: hope so.

21:47 froog: is the problem with mutual recursion by design or implementation?

21:48 chouser: froog: implementation. JVM.

21:48 _ato: froog: you mean the lack of tail call optimization?

21:48 froog: _ato: I mean like: http://en.wikibooks.org/wiki/Clojure_Programming/Concepts#Mutual_Recursion

21:49 that you have to make a forward declaration

21:49 chouser: oh

21:49 requiring forward declarations is a design choice I believe.

21:50 froog: chouser: pity, its a bit of a wart, I think

21:51 chouser: froog: you're not alone in that opinion. If you check the google group you'll find it's been discussed a bit.

21:55 I haven't found it to be a problem.

21:57 froog: chouser: its not enough to put me off clojure :)

22:15 cemerick: it seems that someone could make a better emacs using clojure and one of the IDEs out there. Building from scratch seems a little nuts

22:19 steiger: emacs is very big and quite complex, and great. i see no point in re-doing it

22:19 cemerick: I agree on the big and complex part, but lots of people like tilting at that particular windmill.

22:21 froog: It seems that for every language, at least one person thinks emacs should be rewritten in it

22:21 maybe not brainf*ck

22:25 notallama: mit scheme is emacs redone in scheme, isn't it?

22:30 cemerick: It's just a scheme impl AFAIK

22:31 notallama: maybe you're thinking of PLT scheme, which has a pretty decent IDE?

22:31 chouser: well there scratch and scratch. Java swing comes with pretty much an entire programmable text editor built right in.

22:32 _ato: well rewriting emacs in clojure wouldn't do it as the whole reason emacs is great is that it has so much code already for it

22:33 it'd be nice if someone did something that let you write clojure code to drive emacs and interoperate with elisp libraries, like how you can write clojure code that interoperates with java libraries

22:53 notallama: cemerick: i'm thinking of edwin. it comes with mit scheme, and it knows how to eval scheme, but i'm not sure if it's written in it or not.

22:54 cemerick: chouser: yes, the javax.swing.text API is pretty good, as such APIs go

23:06 hiredman: I sent and email about my reader to clojure-dev

23:06 and screwed up the quickstart instructions twice

23:06 chouser: hiredman: we won't hold it against you. :-)

23:07 hiredman: :)

23:34 chouser: I just glanced at my email and saw "Kevin ... Reader - I have written a Clo..." and I thought a *third* person has written a Clojure reader in Clojure!?

23:34 ...before remembering hiredman's real name. :-)

23:34 hiredman: :P

23:35 I would love to have a third implementation

23:44 cemerick: hiredman: hah, I had no idea what your name was -- I thought, wow, everyone's got their own clojure reader impl these days. :-)

23:45 Of course, chouser just said exactly that. Wow, I'm tired.

23:45 chouser: I haven't talked much about my reader, but it's better than everyone else's. It uses monads.

23:46 I mean it *is* a monad.

23:46 froog: night all!

23:49 chouser: http://tinyurl.com/yf76rln

23:51 notallama: maybe i'll write a clojure reader in clojure. by the time i get to it, it won't be third, though.

23:52 ambient: this like a competition or something? write a clojure reader and win a prize? :p

23:52 notallama: reader golf, perhaps

Logging service provided by n01se.net