#clojure log - Jul 11 2011

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

1:19 jonasen: Does records support metadata?

1:21 sean_corfield: vars support metadata

1:22 so a var that's an instance of a record can have metadata

1:22 is that what you mean?

1:23 hiredman: sean_corfield: a var is a var

1:23 seancorfield_: hiredman: thank you for that :)

1:23 jonasen: could you clarify your question?

1:23 jonasen: not really, maps can hold metadata as in (meta ^{:a :b} {})

1:24 hiredman: seancorfield_: just saying "so a var that's an instance of a record can have metadata" is nonsense

1:24 vars are never instances of a record

1:24 seancorfield_: ok, sloppy terminology

1:25 hiredman: (nonsense)

1:25 chouser: records support metadata

1:25 seancorfield_: which is why i asked jonasen to clarify the question

1:25 jonasen: So I would have guessed that records could too

1:25 chouser: jonasen: yes, they can.

1:25 do

1:25 hiredman: jonasen: what does ^{:a 1} do?

1:25 vs. with-meta

1:26 seancorfield_: chouser: so you can declare metadata with a record type and then add to it when you have a var bound to an instance of that type? i guess i'm having a hard time envisaging it without an example

1:27 jonasen: oh, I thought ^{:a :b} was shorthand for (with-meta ...)

1:27 hiredman: the follow up equestion is: why would with-meta and ^ appear to behave differently for records but the same for maps

1:27 seancorfield_: do you understand how metadata works?

1:28 seancorfield_: hiredman: do you understand how sarcastic you sound? there are ways to explain things without being so condescending

1:28 chouser: (defrecord R [a b]) (meta (with-meta (R. 1 2) {:foo :bar})) ;=> {:foo :bar}

1:29 hiredman: there are two ways to support metadata in clojure, mutable and immutable

1:29 seancorfield_: and?

1:30 jonasen: chouser: If I understand http://clojure.org/reader correctly, (meta ^{:foo :bar} (R. 1 2)) should work too?

1:30 hiredman: jonasen: does (meta ^{:foo :bar} (hash-map :a :b)) work?

1:31 jonasen: so ^{..} only works for literals.

1:32 chouser: ^{} is metadata that is applied to the *form* at *read time*

1:32 hiredman: ^ is for reader metadata

1:32 jonasen: ok, I think I got it now. Thanks all!

1:32 chouser: some things then take that metadata from their form and apply it to an object available at runtime. The data literals do this.

1:34 seancorfield_: ,(meta (with-meta (hash-map :a :b) {:foo :bar}))

1:34 clojurebot: {:foo :bar}

1:35 ibdknox: seancorfield_: sadly some people feel the need to be an ass :( Gotta just shrug it off.

1:40 seancorfield_: (def ^{:foo :bar} v (R. 1 2)) (meta #'v) => {:ns #<Namespace user>, :name v, :file "NO_SOURCE_PATH", :line 12, :foo :bar}

1:41 hiredman: and?

1:41 amalloy: seancorfield_: getting vars involved clouds the picture for no clear purpose

1:41 def (and defn) take the metadata of the symbol (which ^{...} applies at read time) and applies it to the var at evaluation time

1:42 this is a convenience for attaching metadata to vars, which is otherwise difficult, and should not be confused with adding metadata to *values*, like a record

1:43 seancorfield_: right, and i wasn't sure from jonasen's question which he was asking about

1:43 jonasen: seancorfield_: I was asking about metadata on values (specifically maps and records)

1:44 seancorfield_: 'k... so we have the answer to both then

1:48 so what values can have metadata? IObj?

1:51 amalloy: seancorfield_: or IMeta, depending on what you mean by "have"

1:53 jonasen: seancorfield_: symbols and collections according to http://clojure.org/metadata

1:53 seancorfield_: IObj extends IMeta? (sorry, my screen is very small and Clojure Atlas's info doesn't fully fit

1:54 amalloy: &(supers clojure.lang.IObj)

1:54 sexpbot: ⟹ #{clojure.lang.IMeta}

1:54 seancorfield_: &(supers clojure.lang.IReference)

1:54 sexpbot: ⟹ #{clojure.lang.IMeta}

2:01 amalloy: &(let [m {:x 1}] (meta (reify clojure.lang.IMeta (meta [this] m))))

2:01 sexpbot: java.lang.ClassFormatError: Duplicate method name&signature in class file sandbox21497$eval23915$reify__23916

2:01 amalloy: huh

2:02 jonasen: Now I don't understand metadata anymore :). In addition to collections and symbols, all reference types support metadata. Correct?

2:02 seancorfield_: this little discussion has helped me understand (def ^{:foo 1} v ^{:bar 2} {:a :b})

2:02 and why (meta v) and (meta #'v) are different

2:02 amalloy: jonasen: anything that implements IObj can support metadata

2:03 usually it's easiest to avoid working with metadata on reference types, except for what gets added to vars when you def them

2:05 hiredman, chouser: it looks like the compiler automatically imlements IObj for you when you reify an object. is there some reason for that?

2:13 jonasen: I think what I find confusing is that (def ^{:foo :bar} a) puts metadata on the Var, not the symbol 'a. But something like (with-meta #'a {:foo :bar}) doesn't work

2:14 hiredman: with-meta is for the immutable metadata interface

2:14 ,(doc alter-meta)

2:14 clojurebot: Gabh mo leithscéal?

2:14 hiredman: ,(doc alter-meta!)

2:14 clojurebot: "([iref f & args]); Atomically sets the metadata for a namespace/var/ref/agent/atom to be: (apply f its-current-meta args) f must be free of side-effects"

2:15 hiredman: ^- is what you use for the mutable metadata interface (which is what the reference types use)

2:15 amalloy: ~source alter-meta!

2:17 jonasen: So what are the semantic differences for metadata on values vs. reference types?

2:18 hiredman: ,(let [a {}] (identical? a (with-meta a {:foo 1})))

2:18 clojurebot: false

2:18 amalloy: welllll, reference types mutate their metadata in-place

2:19 hiredman: ,(let [a (ref 1)] (identical? a (alter-meta! a assoc :foo 1)))

2:19 clojurebot: false

2:19 hiredman: uh

2:19 right

2:19 ,(let [a (ref 1)] (identical? a (do (alter-meta! a assoc :foo 1) a)))

2:19 clojurebot: true

2:19 jonasen: amalloy: and with values a new value is returned with different metadata

2:23 seancorfield_: nice example that with-meta can't be used with (ref 1) but alter-meta! can

2:36 amalloy: seancorfield_: an interesting exercise to make sure you know what's going on is to implement clojure.contrib.def/defalias

2:37 defining an alias for a macro, with all the correct metadata copied, is harder than it looks

2:43 ihodes: coming into this way late; the meta hashmap on a Var is just a field in the instance of the var, right?

3:00 seancorfield__: amalloy: yes, congomongo used defalias and we just dropped that when moving it to clojure 1.3 since that macro has not been promoted to new contrib

3:01 i'm not sure i really understand why defalias is all that useful

3:01 enlightenment?

3:01 amalloy: ihodes: yes

3:01 but it's an implementation detail that could change, etc etc

3:03 seancorfield__: it's not really useful, but it can be convenient. eg, if you like to use complement the long name is a pain, and you might choose to call it ! instead. or you want to re-export some var from another namespace into yours (though this usage has some pitfalls)

3:07 seancorfield__: so, like exporting foo* from an internal namespace to foo in the main namespace?

3:08 amalloy: something like that

3:09 of course you can just (def ! complement), but then you don't get the metadata like :arglists for slime, and it won't work for macros

3:10 seancorfield__: 'k good to know the downside

3:22 ihodes: IFn.java has really grown hasn't it? whew.

3:23 amalloy: (defmacro defalias [dst src] `(let [v# (var ~src)] (doto (def ~dst @v#) (alter-meta! (constantly (meta v#)))))) is more or less what you need, if anyone is curious

3:23 ihodes: let's throw in type hinting for ints and floats while we're at it. and support at least arity of 6. i mean, come on, that file can stand to grow some more ;)

3:31 what does RT stand for? in clojure.lang

3:36 amalloy: runtime

3:50 ihodes: amalloy: ah, thanks. of course.

6:08 bulters: anyone here happens to get slimv working with macvim?

7:28 bsod1_: how can Clojure supports adding different types in a java data structure like hashmap or arraylist?

8:10 peteriserins: how to see if two lists are the same object?

8:23 ok it was identical? that I needed

9:02 chouser: peteriserins: Under normal circumstances you shouldn't need to know that about lists. What are you doing?

9:06 gfrlog: man using defrecord makes my lein workflow different

9:22 chouser: gfrlog: really?

9:27 ffailla: /join #thortech yorktown

10:52 bpr: ping technomancy

11:08 gfrlog: chouser: yeah, I had issues with stale record definitions that required "lein clean", which I almost never have to do otherwise

11:08 chouser: bleh

11:13 gfrlog: chouser: in lein's defense, I had an older version (though I don't know which one)

11:14 chouser: I think it's Clojure's fault, not lein's

11:15 But maybe nothing can be done

11:16 if you have an instance of an old defrecord around, re-running defrecord has to create a new class and the old instaces won't act the same as the new ones

11:17 cemerick: yeah, not a lot that can be done there

12:09 * cemerick is blowing his blogging budget for the week with this survey results post

12:11 Scripiology: about time :p

12:11 * cemerick puts off the survey results post for another week, just for Scripiology

12:11 cemerick: ;-)

12:13 Scripiology: noooooo

12:14 * Scripiology delays the advance of science in revenge

12:31 tibbe: cemerick: I want to see it too so I can follow up with this year's Haskell survey ;)

12:42 * gfrlog appreciates the alliterative characteristic of "blowing his blogging budget"

12:43 * gfrlog wonders about potential definitions of a word "bludget"

12:45 Scripiology: yay, ideas I'm learning from Clojure seem to carry over with reasonable efficiency to PHP

12:45 actually, never mind

12:46 chouser: ha!

12:50 pyr: any pallet users ?

12:50 around i mean :)

12:51 __name__: pyr: http://upload.wikimedia.org/wikipedia/commons/7/74/Wooden_pallet_with_glove.jpg that?

12:51 Not the glove …

12:55 pyr: nope, https://github.com/hugoduncan/pallet that :)

12:55 sritchie: pyr: yes, but you may have more luck in #pallet

12:55 pyr: ah, nice to know it exists :) will head off there

12:55 sritchie: see you there!

13:55 shintaku: how should i install clojure on mac os x so that the repl doesn't suck in iTerm2? should i use rlwrap? or should i try clojure out with one of the newer jline versions out there, such as the one used for scala?

13:55 amalloy: jline is terrible. use rlwrap

13:56 hiredman: I suggest using the repl that comes with your editor

13:56 shintaku: actually, the jline that ships with scala is not so bad

13:56 with scala 2.9+

13:56 hiredman: you obviously haven't tried using clj in iTerm2

13:57 ohh

13:57 you said editor

13:57 my mistake

13:57 hiredman: I have yet to see a decent shell launcher script for clojure

13:58 mdeboard: emacs++

13:58 hiredman: I think people are only interested in having one for about the first month or so using clojure and after that there is no strong desire to have one, so the onse out there are junk

13:58 shintaku: i googled for rlwrap and clojure and was told to download a bunch of scripts so i stopped

13:58 they were all outdated too: http://trac.macports.org/browser/trunk/dports/lang/clojure/files/

13:58 hiredman: ugh

13:58 no

13:59 anytime you are using the jvm and you say something like "I used my systems package manager to ..." you are doing it wrong

13:59 shintaku: pretty much. i was just downloading those files separately

14:00 mdeboard: hiredman: ...to install OpenJDK? Serious question, can you explain?

14:00 scgilardi: "lein repl" works and uses rlwrap if present.

14:01 hiredman: mdeboard: well no, not the jvm itsself, but in almsot all cases installing jars via the system package manager is the wrong thing to do

14:01 mdeboard: Why? I mean, is there a reason apart from the general awfulness of most package managers?

14:02 hiredman: mdeboard: they assume they way your language works is a global code space (see C, and C language conventions) which is not what the jvm has

14:02 the way

14:03 scgilardi: maven (and maven-compatible tools) do a better job of retrieving current versions of jars than system package managers.

14:05 hiredman: each running jvm is a different virtual machine and gets a different classpath (like every application getting a unique LD_LIBRARY_PATH), there is no shared /usr/lib, etc

14:05 different world from what package managers are written for

14:05 technomancy: debian at least is strongly geared towards packaging up applications for end users. if you're a developer, that model is unhelpful because you need things like multiple versions of the same library to co-exist on a single machine

14:06 so if you just want to use hudson or whatever, that usually works. if you want to use lucene, apt-get is not going to be helpful.

14:06 err--I mean jenkins. sheesh.

14:11 mdeboard: Yeah lein reminds me a lot, at least superficially, of RVM for Ruby

14:11 technomancy: that's funny since I quit using ruby right before rvm was written

14:11 kumarshantanu: can anybody tell why does this throw FileNotFoundException — (clojure.java.io/reader "file:///tmp")

14:12 amalloy: you can't read characters from a directory

14:12 hiredman: kumarshantanu: reader may not expect a file url

14:12 "/tmp"

14:13 amalloy: hiredman: it's happy to take URLs

14:13 it just can't read directories. you have to open them as File objects and then list them

14:13 technomancy: yeah, not really sure what you're expecting from that

14:14 mdeboard: technomancy: I'm a big-time beginner with Clojure (ergo Lein) and a novice iwth Ruby, but rvm is great, and I really prefer it to virtualenv for Python.

14:14 kumarshantanu: hmm, so it should not say "No such file or directory" in the exception then — just "No such file"

14:15 amalloy: kumarshantanu: blame your OS

14:15 mine says: /tmp (Is a directory)

14:16 technomancy: "no such file or directory" is also the exception you get when you try to run a 32-bit executable on a 64-bit OS. it's just JDK nonsense.

14:16 * technomancy has filed that bug before

14:17 kumarshantanu: using the default JDK (1.6.0_26) on 64-bit Snow Leopard

14:18 okay

14:24 brettkromkamp: good afternoon

14:25 clojure n00b

14:25 on the block :-)

14:25 tufflax: ni

14:25 hi

14:25 brettkromkamp: hi

14:26 well... when i say clojure noob, probably functional programming noob is a better description

14:26 tufflax: state of clojure 2011 results are not up yet, right?

14:26 Scripiology: tufflax: I think he's working on them today

14:26 tufflax: oh nice

14:26 Scripiology: or at least some time this week

14:26 mdeboard: Wait, what?

14:26 brettkromkamp: i hope i have come to the right place to ask some really beginners questions

14:26 tufflax: mdeboard ?

14:26 Scripiology: brettkromkamp: go for it!

14:27 mdeboard: State of Clojure? What a pointless speech. Clojure's state never changes.

14:27 brettkromkamp: i've installed emacs

14:27 mdeboard: badum-pshhhhh

14:27 brettkromkamp: installed clojure mode

14:27 installed swank and slime

14:27 mdeboard: stop

14:27 brettkromkamp:

14:27 uninstall swank and slime

14:27 brettkromkamp: got some clojure books

14:27 everything seems to be working

14:27 repl responding

14:27 mdeboard: which repl?

14:27 brettkromkamp: no apparent problems there

14:28 no... my questions are bigger than configuration/installation issues

14:28 mdeboard: clojure repl

14:28 clojure 1.2.1

14:28 all working fin

14:28 *fine

14:29 goto start on my version of "hello world"

14:29 which is: http://www.quesucede.com/page/show/id/python_tree_implementation

14:29 mdeboard: this is a very lengthy setup

14:30 brettkromkamp: implementing a tree structure

14:30 in clojure

14:30 i know

14:30 by all means, bail out if you get board with me/it :-)

14:30 trying to make the jump from imperative programmer to functional programmer

14:30 mdeboard: Well, I just started teaching myself Clojure Friday so I thought I might have some help for you, just waiting for the question

14:31 brettkromkamp: ok... here goes

14:31 in python, my tree structure is stored in a list

14:31 and i append 'nodes' to the list

14:31 but in clojre

14:31 *clojure

14:31 everything is supposed to be immutable

14:31 so... when i apped a node to this list

14:32 what is actually happening?

14:32 Scripiology: using something like conj/cons?

14:32 brettkromkamp: am i getting a *new* copy of the list with the appended node?

14:32 yep

14:32 tufflax: you get a new list, that shares structure with the old one

14:32 Scripiology: it will create a new list with the new node prepended to the old list

14:32 brettkromkamp: ah

14:32 Scripiology: but the original list is unchanged, of course

14:32 brettkromkamp: so that doesn't mean that for each newly appended node

14:33 tufflax: sharing structure makes it fast, and it is safe because they are immutable

14:33 brettkromkamp: i get a completely new list back

14:33 ?

14:33 Scripiology: yes

14:33 mdeboard: yep

14:33 brettkromkamp: say i append 100 nodes

14:33 do i have 100 list structures floating around

14:33 in memory

14:33 ?

14:33 Scripiology: brettkromkamp: note what tufflax said

14:33 mdeboard: Joy of Clojure has an amazing explanation of immutable state, if that's one of your books

14:33 dnolen: brettkromkamp: garbage collection

14:33 tufflax: for a list (linked list) you get a 100 long list, but 100 different pointers into it

14:33 brettkromkamp: mdeboard

14:34 mdeboard: it is

14:34 mdeboard: brettkromkamp: section 1.4.1

14:34 go read it :)

14:34 Scripiology: dnolen: I think he meant doing a 100 conses in a row and storing that, so gc wouldn't have come in yet

14:34 mdeboard: It's so good I memorized the section

14:34 brettkromkamp: i do

14:34 checking it now

14:35 Scripiology: brettkromkamp: you know how a linked list works? Clojure's list is similar, except that the sequence abstraction lets you think of each node in the linked list as a list of its own

14:35 brettkromkamp: scripiology: linked list? yes... i know how they are implemented (in high-level terms)

14:36 Scripiology: cool, let's start from the beginning, say you have a list of one item: '(3)

14:36 brettkromkamp: ok

14:37 said list also represents a given 'state' right?

14:37 Scripiology: inside the Clojure runtime this equates to having one object of class PersistentList (and an empty list object at the end of that, but that's not relevant right now)

14:37 brettkromkamp: ok

14:37 Scripiology: yep, a list can be considered a 'state', but we can cover that later

14:37 brettkromkamp: ok

14:37 Scripiology: so, say you do (cons 2 '(3))

14:37 brettkromkamp: ok

14:38 Scripiology: this creates a new list that's the same as '(2 3), however, what Clojure does is create a new object of PersistentList which stores 2, and also stores a pointer to the original PersistentList that stores 3

14:39 jonabbey: it's one of the coolest things about clojure, actually

14:39 Scripiology: when you call (first '(2 3)

14:39 )

14:39 brettkromkamp: ok

14:39 mdeboard: oh, awesome

14:39 did not know that

14:39 tufflax: So if you do (def a '(3)) then (def b (cons 2 a)), the '(3) part of b is = to a

14:40 Scripiology: what happens is you call first on a PersistentList object that stores 2 and also happens to store a pointer to the list that just contains 3

14:40 tufflax: well, not just = in the clojure sense

14:40 Scripiology: and that call to first() returns 2

14:40 mdeboard: Huh

14:40 Scripiology: when you call (rest '(2 3)) Clojure follows a pointer to that original list and returns that

14:40 * mdeboard scratches his chin

14:40 brettkromkamp: ok... that makes sense

14:40 proper linked-list

14:41 Scripiology: so if you do (first (rest '(2 3))) it gets that original list and calls first on it, which returns 3

14:41 mdeboard: so if you've got '(2 3 4 5 6), and call (rest '(2 3 4 5 6)), it's only going to retrieve that next pointer

14:41 or rather, that next List object

14:41 Scripiology: mdeboard: exactly!

14:41 mdeboard: Huh

14:41 mind:blown

14:41 brettkromkamp: btw... what about performance considerations?

14:41 with increasingly longer and longer lists

14:41 tufflax: what about them

14:41 Scripiology: which considerations specificlly?

14:42 a list of length 1000 is stored in memory as 1000 PersistentList objects

14:42 tufflax: Btw the other data structures also share structure but it is a litte more complicated

14:42 Scripiology: nothing more

14:42 brettkromkamp: does clojure transverse a list from beginning to end if for example i 'access' the last item in a list?

14:42 Scripiology: yep, PersistentVector is a bit less efficient than PersistentList in terms of memory storage, but that's because it's optimized for appending to the end and random access

14:42 tufflax: brettkromkamp yes

14:43 Scripiology: brettkromkamp: for lists, yes

14:43 brettkromkamp: so if you know you'll do that, it's best to use a vector

14:43 mdeboard: vectors aren't hashed then?

14:43 brettkromkamp: ok... so does list lookups perform better for items at the beginning of a list as opposed to items at the end of a list

14:43 ?

14:43 Scripiology: which has O(log32(n) speed

14:43 for accessing values inside the array

14:44 brettkromkamp: for lists, yes, because it's in linear time, but like I mentioned above for vectors it's logarithmic time

14:44 tufflax: mdeboard no, they are trees, just like hash maps, but instead on a hash they use the index to index into it

14:44 Scripiology: mdeboard: check out http://blog.higher-order.net/2009/02/01/understanding-clojures-persistentvector-implementation/

14:44 tufflax: of*

14:44 mdeboard: trees? Having trouble figuring that out. A tree where every node is an edge?

14:45 Scripiology: great explanation of PersistentVector

14:45 brettkromkamp: ok... making sense, guys :-)

14:45 so... big question

14:45 mdeboard: brettkromkamp: I really suggest if you're using clojure mode to also use the slime-repl inside emacs. Makes life very easy

14:45 brettkromkamp: mdeboard: doing just that - absolutely love it

14:45 jimi_hendrix: is there something like the rest function that returns a string?

14:46 mdeboard: then why did you install slime and swank :(

14:46 jimi_hendrix: (rest "foo") -> "oo"

14:46 technomancy: ,(subs "foo" 1)

14:46 clojurebot: "oo"

14:46 jimi_hendrix: thanks

14:46 brettkromkamp: mdeboard: for swank i'm using leiningen

14:46 mdeboard: ,(str (rest '(1 2 3)))

14:46 tufflax: jimi_hendrix not quite

14:46 clojurebot: "(2 3)"

14:46 jonabbey: i'm still trying to figure out lein/slime/swank, etc.

14:46 brettkromkamp: sorry if i didn't explain myself properly

14:46 tufflax: ,(rest "foo")

14:46 clojurebot: (\o \o)

14:47 Scripiology: yea, rest calls seq() on its argument, and for strings it returns a character array

14:47 technomancy: clojurebot: quit starin at me; you're creeping me out

14:47 clojurebot: Cool story bro.

14:47 brettkromkamp: big question for you guys [well, it is big for me]

14:47 S11001001: )

14:48 brettkromkamp: really grokking functional programming if you come from imperative programming [like the majority of us, i suppose]... how did you guys go about that?

14:48 jonabbey: you just get your hands dirty with it

14:48 hodapp: first, you find all the people who tell you you should write in C++

14:48 brettkromkamp: java, python, etc... all about objects with mutable state

14:48 hodapp: then you hit them with a clue-by-four repeatedly

14:49 technomancy: you have to write code. it may be embarrassing to you later, but it's the best way to get your brain in gear

14:49 Scriptor: brettkromkamp: I read a bit of LearnYouAHaskell and tried to implement some of the functions it introduced without looking at the source for them

14:49 brettkromkamp: ok

14:49 mdeboard: Scriptor: oof

14:49 Haskell was way, way, way hairier for me

14:49 brettkromkamp: but haskell is too much of a brain-fuck [pardon my language] :-)

14:50 hodapp: well, at least it's not C++

14:50 tufflax: brettkromkamp I used python before clojure, and in python I was pretty fond of map, filter and reduce. I guess I was just progressing towards fp

14:50 mdeboard: brettkromkamp: My background is in Python & JS. Like technomancy said you just have to write code. I rewrote a Python app I did a long while ago in Clojure this weekend and learned a ton.

14:50 brettkromkamp: but did any of you guys have a 'aha' moment when it just clicked? and, if yes, what made it click?

14:50 Scriptor: brettkromkamp: heh, for functional programming it's not too bad once you get past the first couple of hurdles

14:50 mdeboard: tufflax: tsk tsk

14:50 Scriptor: definitely

14:50 mdeboard: brettkromkamp: I have had several aha moments reading Joy of Clojure

14:50 Scriptor: though I needed several aha moments

14:51 brettkromkamp: ok

14:51 Scriptor: brettkromkamp: start simple, like implementing a count function to return the length of a list

14:51 brettkromkamp: so... just take an existing algorithm or app in an imperative language and convert to clojure?

14:51 mdeboard: brettkromkamp: That's been a big help for me.

14:51 brettkromkamp: And seriously, read Joy of Clojure

14:51 like, right now :P

14:51 tufflax: mdeboard brettkromkamp try this http://4clojure.com/

14:52 mdeboard: clojurians

14:52 brettkromkamp: and just hit my head against the wall until i get it [or have brain a brain concussion :-)]

14:52 mdeboard: yeah

14:52 hodapp: I should be writing these books down. I've messed with Lisp a bit, but not Clojure, yet

14:52 mdeboard: once I got my app rewritten last night I turned off the computer and went to bed

14:52 completely wore me out, felt like I gave birth

14:52 hodapp: lol

14:53 brettkromkamp: mdeboard: lol

14:53 hodapp: was it Paul Graham who said that writing a program was the closest thing to giving birth that males could do?

14:53 mdeboard: then woke up at 9p and read JoC for 2 hours :(

14:53 brettkromkamp: tufflax: thanks - am checking it out as we speak

14:53 amalloy: tufflax: whew, just finished reading the scrollback and was worried i'd have to advertise 4clojure myself. now i can just be subtle and let you do it

14:53 mdeboard: spent the entire weekend working on it.

14:53 jimi_hendrix: mdeboard, JoC?

14:53 tufflax: :)

14:53 jonabbey: the first time i studied lisp, it wound up getting into my head so much that i found myself in bed with my girlfriend, and everything she said my brain was permuting into prefix order

14:53 Scriptor: I still have to write a major clojure app...:/

14:54 just browse through some of the source every now and then

14:54 jonabbey: ooh, 4clojure, nice

14:54 brettkromkamp: scriptor: that brings me to another question... who has written a major clojure app? and what kind of app is it?

14:55 just to get a feel for the kind of problems that are being solved in clojure

14:55 tufflax: brettkromkamp im trying, im working on a online rpg :p

14:55 amalloy: clojurebot: source?

14:55 clojurebot: source is http://github.com/hiredman/clojurebot/tree/master

14:55 tufflax: an*

14:55 Scriptor: brettkromkamp: lots of people have writtens decent-sized clojure codebases, as in more than toys

14:55 amalloy: $whatis source

14:55 sexpbot: source is http://github.com/cognitivedissonance/sexpbot

14:55 hiredman: http://dev.clojure.org/display/community/Clojure+Success+Stories

14:55 Scriptor: hiredman: thanks, was about to hunt for that :)

14:55 amalloy: brettkromkamp: you can look at the source for #clojure's bots as examples

14:55 mdeboard: jimi_hendrix: Joy of Clojure

14:55 jimi_hendrix: ah

14:56 tufflax: brettkromkamp http://cemerick.com/2010/06/07/results-from-the-state-of-clojure-summer-2010-survey/ the 2011 should be up soon too

14:56 brettkromkamp: thx guys - you are being really helpful

14:56 dnolen: brettkromkamp: Twitter's using Clojure now

14:56 Scriptor: dnolen: they're using both clojure and scala?

14:56 brettkromkamp: dnolen: is it? i though they had migrated to scala

14:56 amalloy: brettkromkamp: well, they bought backtype

14:56 dnolen: Scriptor: Twitter bought BackType, BackType is and will continue to build out their Clojure code base.

14:56 symbole: Scriptor: Write an Emacs killer. Put this putty to sleep already.

14:56 mdeboard: I feel like, "State of Clojure every year? Why? Clojure's state is immutable!" is an A+ pun.

14:56 symbole: puppy*

14:57 brettkromkamp: ;-)

14:57 amalloy: mdeboard: c'mon, clojure lets you *manage* state

14:57 cemerick: mdeboard: well done :-)

14:57 mdeboard: I said it earlier to crickets :(

14:57 amalloy: mdeboard: i applauded while i was reading the scrollback

14:57 mdeboard: Anyway brettkromkamp #clojure is a great channel. Unwashed masses haven't started showing up yet.

14:57 #python is kind of a cesspool, for example.

14:58 Scriptor: symbole: I know someone in another channel who was doing a vim clone in clojure

14:58 mdeboard: have you checked out ##php?

14:58 hiredman: there was a lot of talk at one point about "oh, clojure as functional dynamic language will be good for the frontend and because of scala's static nature and types it will be good for the backend" but the majority of stacks I know of are clojure on the backend and rails on the frontend

14:58 jimi_hendrix: mdeboard, i love how "lol" is banned in #python

14:59 also, #d is the worst language channel i have seen

14:59 mdeboard: Scriptor: no

14:59 Scriptor: mdeboard: lucky

15:00 brettkromkamp: so... using clojure to build a combined marketing intelligence and scenario planning system makes sense? :-)

15:00 that's why i am looking into it...

15:00 it => clojure

15:00 tufflax: using clojure to build just aboul anything makes sense, the using clojure part

15:00 at least

15:01 Scriptor: how suitable would clojure be to writing a VM?

15:01 since it's entirely based on mutating

15:01 amalloy: brettkromkamp: ∀x, using clojure to build x makes sense

15:01 jimi_hendrix: just curious, how is clojure speed wise? how does it compare to normal java?

15:01 brettkromkamp: ok

15:02 dnolen: jimi_hendrix: you can get Java speed if you write nasty code.

15:02 jimi_hendrix: lol

15:02 brettkromkamp: dnolen: but clojure isn't 'slow' is it?

15:02 tufflax: amalloy is shows up as a back square for me, your qualifier :p

15:02 jimi_hendrix: thus defeating the point

15:02 clojurebot: the point of moby dick is "be yourself"

15:02 Scriptor: brettkromkamp: nope, it's very nice speed-wise

15:02 dnolen: brettkromkamp: no, it's quite fast.

15:03 brettkromkamp: not like python or ruby?

15:03 amalloy: tufflax: sad. fix your unicode support?

15:03 jimi_hendrix: not at all! just write nasty code in the places where you really have to

15:03 tufflax: maybe :p

15:03 jimi_hendrix: brettkromkamp, even those can be quite fast if you use the right interpreter

15:03 brettkromkamp: python -> cpython and ruby -> mri

15:03 that's what i'm using and i sometimes feel the pain

15:04 dnolen: jimi_hendrix: was being a bit facetious of course. what amalloy said is closer to the truth.

15:04 jimi_hendrix: brettkromkamp, i know the EVE online servers use stackless python for all their processing

15:04 jonabbey: the ability of clojure code to be neatly paralellized is very exciting

15:05 dnolen: brettkromkamp: big draw to me for Clojure was that you didn't have leave the language to write low level fast stuff when you want/need it.

15:05 jonabbey: write in a functional manner, and then spread those functions out across all your processing resources

15:05 brettkromkamp: jimi_hendrix: yeah... i heard... but although i like python it does seem like from an evolution point of view... it is at a dead end

15:05 don't know why it gives me that impression, but it does

15:06 Scriptor: brettkromkamp: pypy's doing some pretty good work on the speed end, but language-design wise you might be right

15:06 brettkromkamp: clojure gives me the impression that we haven't seen nothing yet - despite the fact that it is slow in terms of version updates

15:06 slow version updates does not mean a bad thing

15:07 mdeboard: Yeah agree about Python plateauing. But its ease of use and multiparadigm design will make sure it's around forever.

15:07 brettkromkamp: if i was going on a trip to mars

15:08 would i take clojure or would i take python [if i was only allowed one language]... it would be clojure... without a doubt and i don't even know the language yet

15:08 and i *really* do know python

15:08 hodapp: I am a fan of Python.

15:08 brettkromkamp: so am i

15:08 tufflax: brettkromkamp about having seen nothing yet: lisps have been around for quite some time :p

15:08 Scriptor: might be hard sending new clojure versions to mars :p

15:09 hodapp: although it can be tough to write in Python after having written in C++, MATLAB, and so on for awhile, because you tend to choose harder ways to solve things before realizing Python has a one-line answer

15:09 brettkromkamp: tufflax you are right - but i mean clojure specific -> concurrency, specifically

15:10 anyway... thanks guys

15:10 you have pointed me in the right direction -> rtfm :-)

15:10 tufflax: thanks for making the clojure community bigger :p

15:10 brettkromkamp: the manual being "the joy of clojure"

15:10 tufflax: brettkromkamp and clojure.org!

15:11 brettkromkamp: will do

15:11 already have it as my home page :-)

15:11 tufflax: hehe

15:12 brettkromkamp: talk to you guys later - and again... thanks for all your advice

15:12 Scriptor: no prob!

15:13 babilen: brettkromkamp: I wouldn't necessarily start with "The Joy of Clojure" but with "Practical Clojure" -- Read tjoc afterwards. :)

15:14 mdeboard: babilen: Why's that? I'm new to FP in general and find JoC *extremely* accessible.

15:15 babilen: mdeboard: I found JoC to be better suited after you have at least a little experience and quite liked PC -- Although the "List of api calls"-Chapters in PC are bad.

15:16 mdeboard: I dunno, maybe. But as a beginner to Clojure, the JVM and FP in general Joy of Clojure is amazing and eye-opening. First tech book I've ever been excited to get back to after work.

15:16 babilen: mdeboard: I am not saying that JoC is bad or so, it is a wonderful book, but *I* started with "Programming Clojure" and couldn't quite get into it, then switched over to PC.

15:17 mdeboard: Indeed, it is great. I am curious what Programming Clojure 2nd Edition will be like.

15:17 flazz: i created a project with lein, how do i play with functions in the repl?

15:17 amalloy: (inc mdeboard)

15:17 sexpbot: ⟹ 1

15:18 amalloy: i read JoC first

15:18 babilen: But I am by no means a veteran in Clojure and there might also be technical or style-wise reasons to prefer one book over the other. I just had the impression that PC + JoC is a very good combination.

15:18 amalloy: no previous functional experience

15:18 babilen: I can not really comment on reading JoC first as I have never done that.

15:19 amalloy: flazz: cd myproj && lein repl?

15:19 brettkromkamp: ok...

15:20 just to make sure i've understood you guys [i'm slow on the uptake]

15:20 flazz: amalloy: right, got there; how do i load/run code i wrote in the lib dir in the repl?

15:20 amalloy: blerg. don't write code in the lib dir

15:20 brettkromkamp: it's ok in clojure to use a list as the container for the 'nodes' for my tree implementation?

15:21 appending/cons-ing nodes to a list is not 'bad' clojure practice

15:21 or is it?

15:21 mdeboard: vectors are specifically designed for appending

15:21 Scriptor: brettkromkamp: depends, appending is faster for vectors

15:21 mdeboard: s/designed/optimized

15:21 sexpbot: <mdeboard> vectors are specifically optimized for appending

15:21 brettkromkamp: ok

15:21 mdeboard: lol, nice bot.

15:21 Scriptor: brettkromkamp: you'd normally use conj insted of cons, actually

15:22 conj prepends to lists and appends to vectors

15:22 brettkromkamp: regardless of the actual underlying data structure

15:22 from a fp point of view

15:22 Scriptor: actually, conj calls the equivalent method on the list object it's given

15:22 equivalent meaning the object's own conj method

15:22 brettkromkamp: there is nothing wrong with using a list/vector as the container for a data structure and updating said data structure

15:22 ?

15:22 Chousuke: it's fine to use any data structure that provides the operations you need :)

15:23 amalloy: just avoid *mutating* data structures if you can help it

15:23 brettkromkamp: i'm just trying to wrap my head around this whole 'immutable' state thing

15:23 Chousuke: every clojure data structure is persistent and so good to use

15:23 flazz: amalloy: sorry src dir

15:24 brettkromkamp: amalloy: that's exactly what i mean - what do you mean with "just avoid mutating data structures" how do i work with them if i don't mutate them???

15:24 Chousuke: brettkromkamp: it's not that difficult in the end; instead of "changing" something you transform it

15:24 brettkromkamp: and end up with both the original and the transformed version

15:24 brettkromkamp: chousuke: isn't that horribly inefficient

15:24 ?

15:24 Chousuke: brettkromkamp: no

15:24 jonabbey: clojure's data structures are designed to work that way

15:24 Chousuke: brettkromkamp: clojure data structures do structural sharing

15:25 brettkromkamp: so when i cons or conj - what am i doing? mutating? or transforming?

15:25 Chousuke: transforming

15:25 Scriptor: brettkromkamp: remember how each PersistentList I mentioned before pointed to the next one? That's how lists share structure

15:25 brettkromkamp: perhaps it is just the semantics that i am not understanding

15:25 Scriptor: transforming

15:25 jonabbey: if you do a transformation that shrinkis a data structure and then just keep a reference to the shrunken transformed structure, gc will get rid of the unnecessary pieces

15:25 amalloy: ugh transform is not a word with clear meaning here

15:26 you are creating a new version of the list/vector/whatever

15:26 Chousuke: brettkromkamp: it is slightly less efficient than mutating things, but it's worth the benefits:)

15:26 jonabbey: but if you have a var or a thread that is still referencing the old (larger) version of the structure, it will be kept around as needed

15:26 mdeboard: 15:26 <amalloy> you are creating a new version of the list/vector/whatever

15:26 amalloy: &(let [x [1 2], newx (conj x 3)] [x newx])

15:26 sexpbot: ⟹ [[1 2] [1 2 3]]

15:26 mdeboard: this

15:26 brettkromkamp: ok... this is the real head-fuck with regards to clojure

15:26 jonabbey: by transform, read the output of a function that returns a modified version of a structure

15:26 amalloy: here i conjed onto a vector, and the old and new versions are both still in existence

15:26 Chousuke: brettkromkamp: note that most programs do need mutable state. But clojure handles that with another mechanism

15:26 brettkromkamp: ie. with reference types

15:27 brettkromkamp: ok

15:27 jonabbey: or by simply calling methods on java objects, if you like that sort of thing

15:27 amalloy: Chousuke: no programs *need* mutable state. but often it's easier to write/model them if you use some

15:27 Chousuke: brettkromkamp: references mutate, but the data structures that they refer to do not

15:27 mdeboard: brettkromkamp: It need not be a headfuck. Every time you change something about a collection, you get a new item back.

15:27 brettkromkamp: i *think* i understand what you guys are saying - but it really does require a different way of thinking about program design

15:27 jonabbey: it does

15:27 hiredman: amalloy: *ahem*

15:27 mdeboard: Chousuke's explanation is muddying the water a bit I think

15:28 Scriptor: mdeboard: it's just explaining how the new item still shares memory with the original that's hard to explain :)

15:28 mdeboard: It's all pointers right?

15:28 jonabbey: references, yes

15:28 mdeboard: So there you go :)

15:29 Scriptor: brettkromkamp: maybe this'll clarify it for you: say you conj onto a vector. In Clojure terms this returns a new vector that's separate from the old one

15:29 brettkromkamp: ok

15:29 * mdeboard mumbles that Joy of Clojure really does an excellent job of illuminating all this in the first two chapters, and that brettkromkamp should really go read it

15:29 Scriptor: but in implementation terms, since the new vector is almost exactly the same as the old one except for one new item, you don't need to copy the old one

15:30 dnolen: brettkromkamp: but really you shouldn't even think about it like that since this all implementation-centric

15:30 amalloy: hiredman: am i wrong? it seems to me you can write any program as a function which takes "the universe" as input and returns a new universe, in conjunction with a loop that iterates over this, possibly doing some i/o

15:30 dnolen: 1 + 1 - > 2

15:30 Chousuke: ,(let [a '(a list) r (atom a)] (swap! a conj 'something) [a @r r])

15:30 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Atom

15:30 brettkromkamp: so... under the hood clojure is inmutable but from a programming point of view... it's business as usual?

15:30 Scriptor: brettkromkamp: so the new vector actually tries to share as many objects as it can with the old one without copying them

15:30 dnolen: you have values and operations on values, you can't change 1 or 2

15:30 Chousuke: wait

15:30 ,(let [a '(a list) r (atom a)] (swap! r conj 'something) [a @r r])

15:30 clojurebot: [(a list) (something a list) #<Atom@199682f: (something a list)>]

15:31 jonabbey: it's business as usual from a functional point of view

15:31 dnolen: you should see (conj {} 'a) should think, that just like (+ 0 1) etc

15:32 jonabbey: i.e., you write functions which take data and return results. clojure's data structures are designed under the covers to make that as efficient as possible for operations on lists, vectors, etc.

15:32 mdeboard: brettkromkamp: For our purposes right now, in answer to your "business as usual" question, yes.

15:32 brettkromkamp: mdeboard i will read the joy of clojure - sorry about this

15:32 jonabbey: and clojure's persistent ("immutable") data structures have unique benefits when you're running multithreaded

15:33 mdeboard: You can write a million lines of operational code in Python without ever understanding the concept of state mutability

15:33 it will augment your ability for sure

15:33 brettkromkamp: me -> off to read the first chapters of the joy of clojure

15:33 mdeboard: I'm p sure it's like that in clojure too.

15:33 brettkromkamp: sorry guys

15:33 Chousuke: brettkromkamp: no need to apologise for asking questions

15:33 mdeboard: ^

15:34 I'm at work writing python or I'd be asking them myself

15:34 Chousuke: brettkromkamp: what you're asking might seem simple or "stupid" but it really isn't.

15:34 brettkromkamp: well... i must admit... i do feel a bit stupid

15:35 i've been developing for 10 years now

15:35 that's why i just wanted to talk to other devs

15:35 Chousuke: brettkromkamp: that might be precisely why clojure's concepts are difficult for you

15:35 brettkromkamp: in the company i work for... the other devs just aren't interested in other languages

15:35 let alone fp... oo is everything to them

15:35 Chousuke: it's easier to learn something new when you have no expectations of how things work

15:36 Cozey: is it possible to call a static method of a class, when I have this class as a value ?

15:36 brettkromkamp: true

15:36 jonabbey: learning functional programming / lisp is almost like learning a new human language.. it takes some time to get your brain to think in it

15:36 Chousuke: yeah, but once you get it, it will affect the way you think about all programming

15:36 brettkromkamp: i'll get there [cross fingers] :-D

15:36 Cozey: like: (let [i Integer] (.valueOf i "123" ) ) ?

15:36 technomancy: brettkromkamp: it might be too theoretical, but if you're interested in an explanation for how programs can work without modifying state I recommend reading Out of the Tarpit

15:37 you'll definitely want to read it eventually

15:37 brettkromkamp: out of the tarpit?

15:37 technomancy: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.93.8928&rep=rep1&type=pdf

15:37 jonabbey: nice ref

15:37 technomancy: a short paper on FP; pretty accessible

15:37 amalloy: Cozey: it's possible, but it might need reflection?

15:37 brettkromkamp: what you say... how programs can work without modifying state -> that is hitting the proverbial nail on the head

15:38 jonabbey: for 'state', read 'heap

15:38 Cozey: amalloy: mhm.. so maybe there's another way to serialize an Enum ?

15:38 brettkromkamp: that is exactly what i am looking for

15:38 jonabbey: functional code involves modifying state, but it's state that is thread-private and restricted to active function stack

15:38 technomancy: brettkromkamp: it has a great proof that storing internal state is necessary solely for optimization (called "accidental complexity")

15:39 brettkromkamp: out of the tarpit -> copying to my kindle as we speak :-)

15:39 hiredman: amalloy: seems rather disingenuous to discount the io loop as part of the process

15:39 jonabbey: fun / neat languages to learn: clojure, erlang, prolog

15:39 Chousuke: brettkromkamp: I think most programs need some sort of state, but most of the *code* doesn't. It's possible to separate "stateful" code from code that does things with immutable values.

15:40 technomancy: brettkromkamp: the second half is not as relevant fwiw

15:40 brettkromkamp: technomancy :-D

15:40 Cozey: ah there's a (Enum/valueOf BlaBla "NAME")

15:41 technomancy: clojurebot: Out of the Tarpit is a short, accessible paper on FP and reducing complexity by identifying and minimising state: http://ben.moseley.name/frp/paper-v1_01.pdf

15:41 clojurebot: In Ordnung

15:41 amalloy: Cozey: hah, wish i knew about that when i was serializing enums a while ago

15:41 brettkromkamp: thanks guys -> i'm off to do some reading

15:42 mdeboard: brettkromkamp: So look, instead of feeling stupid, you really need to feel smart as hell in here because Clojure is a very big deal. As a friend of mine says, the consumer Internet has been aruond for ten years. There's no possible way that Python or Ruby is the end-all, be-all of web development. Clojure has undeniable benefits in concurrency and speed that imperative langs, and even multiparadigm langs e.g. py/rb,

15:42 will not be able to match. I'm not saying Clojure is "the next big thing", it probably isn't, but I think the next generation of impure FP langs will be the big ones.

15:42 amalloy: though i think i wanted to serialize to a byte rather than a string

15:42 Chousuke: brettkromkamp: for example, you might have a function that removes all vowels from text. that obviously can be done with a non-stateful function. then you might have an UI with an input field where you want to apply this transition; it requires state, but that is a separate problem... The main logic is still a stateless function.

15:42 Cozey: amalloy: i want to pass mine through a html form

15:43 * mdeboard hasn't been this excited about programming since first learning Python

15:44 dnolen: mdeboard: I don't see any serious competitors for the future FP goto langs beyond Scala & Clojure. Scala from the static typing side, Clojure from the dynamic typing side.

15:45 mdeboard: dnolen: Well, I think the thought patterns of FP will keep Clojure & Scala from reaching widescale adoption. OOP is pretty entrenched

15:46 jonabbey: a generation is being trained to a broader point of view already with python, ruby, and javascript

15:46 mdeboard: ture that

15:46 true*

15:46 dnolen: mdeboard: I don't mean FP will replace OOP anytime soon, but I think the adoption of FP will be quite dramatic in the next few years.

15:47 mdeboard: dnolen: That's what everyone thought in the 70s and early 80s too

15:47 dnolen: mdeboard: except there were very few *production* oriented FP langs.

15:47 mdeboard: also true

15:48 dnolen: Clojure & Scala are both squarely aimed at working programmers.

15:48 jonabbey: with massive pre-existing libary and tooling support

15:48 i remember doing CLOS coding back in the early 90's.. talk about a wasteland

15:49 hodapp: You say "replace OOP" like we currently use OOP...

15:49 jonabbey: i remember when Apple was pushing Dylan hard, too

15:49 hodapp: but the dominant implementations are pretty lacking in terms of actually meeting what Alan Kay had in mind in proposing the term

15:50 jonabbey: isn't Objective C supposed to be pretty decent?

15:50 hodapp: I've heard it is.

15:50 It's closer to Smalltalk

15:51 jonabbey: it supports dynamic method dispatch the way python does

15:51 message oriented

15:51 hodapp: yeah

15:52 I am much a fan of Python's duck typing

15:53 jonabbey: is clojure-contrib 1.2 the latest version, or is there a newer version for use with clojure 1.3.0 beta?

15:54 jweiss_: anyone know of a lib that would let me jump into code the way you do in emacs with M-. but generating HTML with links instead?

15:57 mdeboard: jweiss_: I don't understand the question

15:57 jweiss_: mdeboard: you know what i'm referring to with the emacs M-., right?

15:57 mdeboard: yeah

15:57 it's the "but" clause I don't understand.

15:57 technomancy: jonabbey: individual libraries may have been upgraded to work with 1.3; depends what you want

15:58 jweiss_: mdeboard: i want to take my set of source files, and output html so taht the fn calls are links to the functions they actually call

15:58 jonabbey: okay

15:58 mdeboard: ahh

15:58 brettkromkamp: technomancy, mdeboard, chousuke... thanks guys

15:58 jonabbey: i'll just clone clojure-contrib from github/clojure and go with that

15:58 brettkromkamp: i hope to come back somewhat more enlightened

15:58 jweiss_: mdeboard: obviously, you need some kind of runtime to do that, you can't do it just with the source, but i'm ok with that

15:59 cemerick: well, that took waaaay too long

15:59 State of Clojure 2011 results: http://wp.me/p10OJi-9L

15:59 amalloy: cemerick: you got it done before 2012, anyway

16:00 tufflax: brettkromkamp you might like this http://blip.tv/clojure/clojure-for-java-programmers-1-of-2-989128

16:00 cemerick nice :)

16:01 cemerick: mdeboard: your pun has been immortalized :-P

16:01 mdeboard: cemerick: How's that

16:02 cemerick: mdeboard: OH'ed on twitter

16:02 mdeboard: cemerick: lol

16:02 shit you could've @'d me at least, mattdeboard

16:02 (jk obv)

16:03 s/sh*t/darn

16:03 cemerick: mdeboard: well, see, you should've tweeted it, and then I'd give you a RT

16:03 mdeboard: I don't use twitter anymore, G+

16:03 cemerick: *shrug*

16:03 mdeboard: lol but I'm honored, thanks :)

16:04 cemerick: My G+ profile will likely languish, just like my FB account.

16:04 dnolen: cemerick: it's interesting that people come to Clojure from dynamic langs but would switch to a static lang if Clojure didn't exist.

16:04 cemerick: dnolen: true. I don't think static/dynamic is as much of a divide as it's put up to be.

16:04 imperative vs. functional, though, that's a biggie

16:12 dnolen: cemerick: great stuff, thanks for putting it together.

16:15 paraseba: Is anybody using clj-time with clojure 1.3.0-beta1?

16:28 cemerick: dnolen: Thanks, and np :-)

16:28 mdeboard: cemerick: I can't see it at work :(

16:29 cemerick: really!

16:29 mdeboard: do they just block all of wordpress.com?

16:29 mdeboard: cemerick: probs

16:29 cemerick: bogus

16:31 Scriptor: mdeboard: google cache: http://goo.gl/XbUvl

16:31 hopefully that works

16:31 wait, nvm

16:31 that's the announcement of the end of the survey

16:32 cemerick: I was going to say, no way it's cached already

16:32 mdeboard: it did thanks Scriptor

16:32 oh

16:32 I was like "where's the survey"

16:40 amalloy: cemerick: google caches stuff like mad

16:40 even with some fairly minor SEO you get cached within the hour, iirc

16:41 Scriptor: amalloy: all the more reason why g+ running out of disk space was a serious wtf

16:41 kumarshantanu: hi, need some help with regex-fu — can anybody verify that this (below) is correct?

16:41 ,(re-find (re-matcher #"(.+)\-([\d\.]+)\.(\w+)" "foo-bar-1.0.6.jar"))

16:41 clojurebot: ["foo-bar-1.0.6.jar" "foo-bar" "1.0.6" "jar"]

16:41 amalloy: shoulda headed over to facebook to borrow a cup of sugar

16:42 kumarshantanu: trying to split up arbitrary maven artifact filenames into tokens — artifactId and version

16:42 Scriptor: kumarshantanu: seems to work from what clojurebot printed out

16:42 hiredman: not going to happen

16:42 amalloy: kumarshantanu: fwiw, - doesn't need to be escaped, and nor does . inside of []

16:43 hiredman: jars don't have the groupid in the filename

16:43 kumarshantanu: hiredman: right, i am just trying to get artifact-id and version

16:43 hiredman: I'm not actualyl sure that the artifactId is always in the jar name, could just be most of the time

16:43 actually

16:43 cemerick: ?

16:44 cemerick: hrm?

16:44 oh

16:45 Not having the artifactId in the artifact filename would be *very* rare, but can happen.

16:46 kumarshantanu: amalloy: thanks, yes - and . need not be escaped in []

16:46 cemerick: IIRC, you can attach any file to an install/deploy, with any filename.

16:46 kumarshantanu: do you not have the pom's for these artifacts right next door?

16:47 hugod: there are also classifiers - test, sources, etc

16:47 kumarshantanu: cemerick: hiredman: i am only trying to guess the artifact-id and version

16:47 cemerick: am trying to do a lein plugin…so it'll be user-assisted

16:47 * amalloy usually deploys all of his artifacts with the filename "maven-sucksssss.test"

16:47 kumarshantanu: this is for local JARs

16:48 cemerick: kumarshantanu: well, just know that you're in murky territory.

16:49 kumarshantanu: cemerick: true :)

16:50 cemerick: kumarshantanu: also know that, as long as you're working with local jars, you're working with jars that aren't in a repo, and the build process you're attempting to support will be unrepeatable by default

16:50 :-)

16:50 * cemerick is trying to be optimistic

16:53 kumarshantanu: cemerick: right…am wondering if it can be streamlined a bit — (1) store local JARs in "local" dir, (2) run this lein plugin to install to local-repo, (3) lein deps, (4) lein jar

16:53 checking in JARs in version control is another can of worms though

16:53 hiredman: kumarshantanu: there is a local repo, ~/.m2

16:54 kumarshantanu: hiredman: installing JARs to ~/.m2 is a chore, which is what i am trying to get rid of

16:54 cemerick: kumarshantanu: I don't know what you're attempting to do, and I've never written any lein-related code, I don't really want to say anything unhelpful. But if anything you're doing involves jars into version control systems, please don't.

16:54 hiredman: kumarshantanu: I think you would be better serverd by taking the time to get your jars into a repo

16:55 infact, if you specify an unknown jar in your project.clj, lein will spit out the command needed to install it into the repo

16:56 cemerick: hiredman: can it do it itself, or is it still a mvn incantation?

16:56 hiredman: cemerick: it is an mvn command

16:56 * cemerick shivers @ install-file

16:56 hiredman: for random jars, lein can install and deploy the artifacts it produces

16:57 cemerick: There was a guy around here a year ago or so that was thinking of starting a mvn repo hosting service. I wonder where he went off to.

16:58 hiredman: *shrug* maven repos are dirt simple, dunno how you could make money doing it

16:58 you need GET and PUT and you're done

16:59 cemerick: hiredman: same goes for e.g. gitosis, yet people pay for hosted git repos.

17:00 My mvn-repo-in-github hack is consistently one of my most popular posts, surprisingly. http://cemerick.com/2010/08/24/hosting-maven-repos-on-github/

17:01 hiredman: cemerick: yeah, but the host github repos are git + other features you want anyway, how much is there to build on top of GET and PUT for a maven repo?

17:02 cemerick: There's nothing to build at all — you can just use nexus or artifactory, and have lots more than GET and PUT for free.

17:03 I think it's fundamentally a matter of admin overhead (or not).

17:03 hiredman: mmm

17:18 paraseba: right now, clojure.contrib.condition is broken for clojure 1.3.0, it's not using :dynamic. How is this project going to be maintained? should I send a patch to contrib? should I help to migrate it to its own project?

17:20 technomancy: paraseba: it's in its own project already, actually

17:21 clojurebot: slingshot?

17:21 clojurebot: It's greek to me.

17:21 technomancy: clojurebot: lise

17:21 clojurebot: excusez-moi

17:21 technomancy: I mean lies.

17:21 whatever

17:21 clojurebot: slingshot is the successor to clojure.contrib.condition: https://github.com/scgilardi/slingshot

17:21 clojurebot: Ok.

17:22 paraseba: technomancy: Oh, didn't know about that. Thanks

17:23 technomancy: but, don't you think this kind of problem will slow 1.3.0 adoption?

17:29 ibdknox: do you think clojure/core would be interested in a redesign of clojure.org?

17:37 technomancy: paraseba: yeah, but people need to move off contrib anyway

17:38 it's a left-over from back when the answer to "how do I make it easy for people to use this code" wasn't "publish it somewhere that makes sense"

17:38 paraseba: I agree, but it's hard to know where to move to

17:39 maybe adding some alternative options in contrib modules documentation

17:39 technomancy: slingshot is different because the author wants it to see more internal usage before making a big announcement

17:40 I personally haven't seen many useful old-style contrib libraries that don't have modular replacements

17:40 slingshot was kind of the last missing piece

17:41 paraseba: c.c.def has an alternative?

17:43 amalloy: i think it's fair to say that c.c.def isn't "useful"

17:43 replaca: technomancy: hmmm, an issue with lein repl, lein swank, etc.: if I need a big JVM and I set JAVA_OPTS=-Xmx1024m, the setting applies to both lein *and* the jvm it spins up to run the repl/swank client

17:43 technomancy: defalias hovers on the edge of being justified

17:44 replaca: good point; that's not terribly useful

17:44 replaca: technomancy: I'm not sure if this really matter (the resident set size of lein is quite small) but I could imagine probs for very large virtual sizes

17:44 technomancy: do you know about :jvm-opts in project.clj?

17:44 replaca: ahh, no. That's probably what I want.

17:44 works in both those scenarios?

17:44 technomancy: it applies to the project JVM only

17:45 but if you could open an issue to separate out JVM_OPTS and LEIN_JVM_OPTS that would be super

17:45 replaca: right, but both with swank or repl?

17:45 technomancy: since it's not always appropriate to edit project.clj

17:45 yes, every project JVM

17:45 replaca: yup (in my case it is, though)

17:45 technomancy: all code that needs to run in the context of the project

17:45 replaca: technomancy: issue on the way, thx

17:45 technomancy: cool

17:46 * technomancy finds defdeprecated more useful than anything in c.c.def

17:49 paraseba: technomancy: I agree, the problem is there are lots of libraries depending on c.c.def and others. If all they had to do to move to 1.3.0 was change a namespace, it would be faster

17:49 but also ... it wouldn't help moving out of c.c . So, probably the pain is justified

17:50 amalloy: technomancy: "We have a policy of releasing entire Java packages in which every single class, interface and method is deprecated right out of the box, starting at version 1.0." -- http://steve-yegge.blogspot.com/2010/07/wikileaks-to-leak-5000-open-source-java.html

17:51 not really relevant, i suppose, unless that's why you like defdeprecated

18:07 technomancy: deprecation happens

18:40 dRbiG: right, i have (sort-by (fn [x] (.length (new File path x))) files) - i'd like to make a macro/fn/whatever out of it where i can substitute .length with a string (i check if the string actually is a proper .method before, so no need to worry)

18:41 and this is giving me a headache :S

18:45 ataggart: dRbiG: is there a question?

18:45 dRbiG: ataggart: there is, implicitly, "how would you do it?"

18:46 ataggart: invoke a method on an object using the method's string name?

18:46 ibdknox: does it have to be a string?

18:47 not that it really matters

18:47 &(symbol ".length")

18:47 sexpbot: ⟹ .length

18:49 cemerick: or just use the lower-level form so you don't have to bother with the concatenation: (. (new File path x) length)

18:50 ibdknox: even better

18:50 ataggart: smells like an xy problem

18:50 dRbiG: cemerick: nope,

18:51 ataggart: xy?

18:51 clojurebot: xy is http://mywiki.wooledge.org/XyProblem

18:52 dRbiG: indeed

18:52 dnolen: dRbiG: methods are not first class, they are statically determined.

18:53 ,(doc memfn)

18:53 clojurebot: "([name & args]); Expands into code that creates a fn that expects to be passed an object and any args and calls the named instance method on the object passing the args. Use when you want to treat a Java method as a first-class fn."

18:53 dnolen: dRbiG: is there any reason to use a string and not a function ?

18:54 cemerick: ataggart: probably right, but that wiki page is unfortunate.

18:55 terom: Are there any good examples of memfn use somewhere?

18:56 amalloy: &(map (memfn length) ["test" "strings" "are" "long"]) :P

18:56 sexpbot: ⟹ (4 7 3 4)

18:56 ataggart: largely replaced with the anonymous fn synta

18:56 dnolen: http://clojuredocs.org/clojure_core/clojure.core/memfn

18:56 ataggart: x

18:56 dRbiG: http://en.wikibooks.org/wiki/Clojure_Programming/Examples#Invoking_Java_method_through_method_name_as_a_String

18:56 this does it

18:57 amalloy: sigh. yes, reflection will solve many such problems, but as ataggart says they're usually only problems because you've done something wrong already

18:57 ibdknox: dRbiG: but you have to ask yourself if this is really necessary, resorting to reflection is a sad thing

18:59 dRbiG: maybe as i iterate i'll see better way to do it

18:59 dnolen: dRbiG: what advantage do you see in using strings over functions ?

19:00 * mdeboard` heads to 4clojure

19:01 dRbiG: query string will have ?sort=length, or ?sort=lastModified etc. - so i just want to invoke that inside sort-by; as a chceck against stuff like sort=delete i'll check if the given str is in a predefined list of what's allowed

19:01 ataggart: BTW, the dot is a special form, so you could avoid reflection via a macro

19:01 e.g.: (defmacro invoke-method-name [method target & args] `(. ~target ~(symbol method) ~@args))

19:02 dRbiG: that's the approach i'd take with ruby/io/anything that has nice member? and send

19:02 i guess there's better way to do it here :)

19:03 dnolen: dRbiG: if you're going to check against a predefined list, why not just have map that stores str -> fn

19:03 ataggart: dnolen: nah, just use eval. ;)

19:03 ibdknox: lol

19:05 mdeboard`: Man, 4clojure.com is slow

19:06 Not a random gripe by the way; I'm curious why it's slow. Holy cow look at the source, I assme this is auto-generated by Clojure?

19:06 amalloy: mdeboard`: it is fast as lightning for me

19:07 and yes, hiccup generates the html every time

19:07 mdeboard`: amalloy: page load times are intermittently horrendous and acceptable

19:08 amalloy: mdeboard`: we serve some big javascript files, but we carefully mark them as cacheable

19:08 mdeboard`: Maybe that'swhy

19:08 Raynes: mdeboard`: We don't talk about 4clojure's performance. You're new here, so I'm going to let this slide.

19:08 mdeboard`: It's my first visit

19:08 amalloy: my browser shows a bunch of 304 Not Modified

19:08 mdeboard`: Raynes: Thanks

19:08 Raynes: ;)

19:09 mdeboard`: You know I could rewrite this in Python on top of Flask if you'd like! :D

19:09 I'm kidding of course

19:09 * ibdknox gets out pitchfork

19:09 ibdknox: hehehe

19:10 amalloy: mdeboard`: if you're looking for a small project and you think the html is ugly, you could write a wrapper that pretty-prints the generated html if the url has a ?debug=true

19:11 ibdknox: or just use a DOM inspector, which all modern browsers have :)

19:11 * amalloy still uses IE 4

19:11 ibdknox: amalloy: a winner is you ;)

19:11 mdeboard`: ibdknox: Dom inspectors are good for honing in on a particular bit of content but it is often helpful to me to then view source and Ctrl-F for that bit of content to get context

19:12 ibdknox: hm, you can search the DOM too?

19:12 not sure I understand the distinction

19:13 the only real difference between a pretty printed version of the HTML and what you would get in firebug or webkit's inspection tools is that the JS will have run

19:13 which I would think you'd want

19:13 mdeboard`: Plus I don't have to futz about with resizing the window and can navigate entirely by keyboard without tabbing a million times

19:14 Just personal preferences, not syaying my way is better at all.

19:14 or superior in some way

19:14 It's superior to me because that's how I like doing i t:)

19:14 ibdknox: mdeboard`: yep yep :)

19:19 ndimiduk: ,(contains? [1 2 3] 2)

19:19 clojurebot: true

19:19 amalloy: clojurebot: contains?

19:19 ndimiduk: ,(contains? '(1 2 3) 2)

19:19 clojurebot: false

19:19 contains? is for checking whether a collection has a value for a given key. If you want to find out whether a value exists in a Collection (in linear time!), use clojure.core/some or the java method .contains

19:20 amalloy: ninja'd

19:20 mdeboard`: lol

19:21 ndimiduk: amalloy: why does this not work on seqs?

19:21 amalloy: for the same reason that (= 5 '(1 2 3)) doesn't return 2. it does a different thing

19:22 Scriptor: ,('(0 1 2) 2)

19:22 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn

19:24 mdeboard`: ,(closure.set/intersection #{:a :b :c} #{:b :c :d})

19:24 clojurebot: java.lang.ClassNotFoundException: closure.set

19:24 mdeboard`: wow

19:25 ,(clojure.set/intersection #{:a :b :c} #{:b :c :d})

19:25 clojurebot: #{:c :b}

19:31 leeda: Hi, I'm trying to understand binding... why doesn't this work: (binding [x 1] (println x))?

19:33 hiredman: ,(doc binding)

19:33 clojurebot: "([bindings & body]); binding => var-symbol init-expr Creates new bindings for the (already-existing) vars, with the supplied initial values, executes the exprs in an implicit do, then re-establishes the bindings that existed before. The new bindings are made in parallel (unlike let); all init-exprs are evaluated before the vars are bound to their new values."

19:34 gfrlog: leeda: binding works with vars, which are normally created with (def)

19:34 mdeboard`: Hrm why is (fn [x] (+ x x)) not a valid answer to http://4clojure.com/problem/15 ?

19:35 amalloy: mdeboard`: it is. you must be typoing somewhere? i jsut copy/pasted that and it works

19:35 gfrlog: mdeboard`: it tells me it's valid

19:35 mdeboard`: hm not working for me, I have it on four lines.

19:35 leeda: gfrlog: I see, thanks. So if I do (def x 1), how can I get a per-thread binding for x?

19:35 mdeboard`: :\ if there's four blanks shouldn't it accept four answers?

19:35 gfrlog: leeda: after you've def'd it you can (binding [x ...] ...)

19:36 amalloy: uh. no, you supply an answer, and it uses it in all the blanks

19:36 leeda: gfrlog: ok, I see, thanks!

19:36 gfrlog: leeda: note that in clojure 1.3 you have to add the ^:dynamic metadata to the var

19:36 mdeboard`: amalloy: Hm it works in previous answers

19:36 amalloy: coincidence

19:36 mdeboard`: lol

19:36 leeda: gfrlog: ah ok, I'll look that up

19:36 mdeboard`: amalloy: Kind of like gist's random coloration?

19:36 amalloy: mdeboard`: yeah srsly though

19:38 mdeboard`: I mean for new people inconsistent behavior from the UI is goingto be pretty frustrating

19:38 amalloy: mdeboard`: it's not inconsistent

19:38 mdeboard`: How not

19:38 amalloy: i literally mean that, by coincidence, supplying an answer N times happens to work

19:38 because (= 3 3 3 3) is true

19:38 on, eg, http://4clojure.com/problem/12

19:40 if you supply "3 3 3" as your answer, it splices that string into each __ and then runs all the tests

19:40 mdeboard`: From the perspective of a user, that is 100% inconsistent behavior

19:40 It doesn't matter if mechanically behidn the scenes it's expected behavior

19:40 To the user it's nonsensical

19:41 amalloy: you are the first user to have encountered this "nonsense", perhaps because you didn't read http://4clojure.com/directions?

19:42 * gfrlog is going to wait until 5clojure comes out, due to the current scandal

19:46 mdeboard`: amalloy: Before I say anything else I wanna make clear that I'm not griping about the site (which I infer you maintain?). It's awesome and I'm using it. I just think that something as straightforward as fill-in-the-blank shouldn't require reading instructions. I mean, the only reason I care is because I'd hate for someone to get turned off by unpredictable behavior. If you give a human four problems and the ability t

19:46 o enter in four solutions, I'd wager a lot will do that. I assumed every line was being evaluated individually against its corresponding form. If you like it that way, then cool. Now that I know, I know.

19:47 Scriptor: does anyone know if anyone has written a netflix lib for clojure?

19:47 amalloy: mdeboard`: i don't think a lot of people have thought of it as four problems. it's one problem, with four test cases

19:47 chitsubr: rich hickey's wiki page is nominated for deletion - http://en.wikipedia.org/wiki/Wikipedia:Articles_for_deletion/Rich_Hickey. sheer madness

19:48 mdeboard`: amalloy: Alright.

19:48 amalloy: if you have a suggestion for a good way to improve the UI, or to put into a readme somewhere, i can make it happen

19:48 Scriptor: "Clojure may be notable but its creator may be not" wow

19:49 gfrlog: This feels a lot like Horton Hears a Who. I think we need to start banging pots so the kangaroo can hear us.

19:50 mdeboard`: Nah, I'm probably just being a dummy. Long day at work.

19:50 Scriptor: so...no netflix lib? I has a project!

19:50 amalloy: Scriptor: first go find a java lib for it

19:51 Scriptor: amalloy: but then I won't has a project :p

19:52 ah, http://www.blueleftistconstructor.com/projects/nfjc/current/

19:53 mdeboard`: Wow, that Artem Karimov fella really, really has a stick somewhere about Clojure.

19:53 re: wikipedia

19:54 technomancy: pretty typical of the deletionists crew

19:55 that said, the article isn't terribly informative

19:56 Scriptor: heh, he's an 18-year old kid from moscow

19:56 mdeboard`: I wonder why, say, Guido van Rossum is notable but not Rich Hickey?

19:56 Anywya.

19:57 amalloy: mdeboard`: because he has rabies re: TCO

19:58 and reference counting

19:58 that is basically the one things i know about him: he has terrible ideas about TCO and reference counting

19:59 zodiak: actually, I wonder what mascot clojure would have .. you know.. a nice friendly little thing to put on t-shirts, stickers, etc

19:59 it's all about propaganda ;)

19:59 Scriptor: a lamb?

19:59 mdeboard`: A lamb riding a dragon

19:59 Scriptor: a lamb saying "yes" in Russian :p

19:59 zodiak: I was thinking single cell organism; you know, sort of the building block of life ;)

20:00 mdeboard`: ಠ_ಠ

20:00 ibdknox: why did Clojure go with a mailing list instead of a forum?

20:00 Scriptor: most languages do

20:01 I've also seen very little spam on the mailing list, maybe it's harder to manage on a forum?

20:01 ibdknox: I would think the exact opposite

20:01 mdeboard`: old people love mailing list

20:01 s

20:01 ibdknox: you can moderate a forum

20:01 amalloy: i would have been happy with usenet

20:02 hiredman: mdeboard`: old people?

20:02 Scriptor: ibdknox: also, the google groups website itself acts almost like a forum

20:03 mdeboard`: hiredman: Yeah, you know, everyone older than the person using the term "old people". (I'm in my 30s)

20:03 ibdknox: Scriptor: it's close, but the lack of true moderation makes that less useful I would think

20:03 Scriptor: also, the interface could be greatly improved

20:03 Scriptor: ibdknox: hmm, it allows some moderation

20:03 ibdknox: like having code highlighting and such

20:03 Scriptor: but eh, a lot of programmers like their email clients, I think,

20:03 amalloy: Scriptor: or news clients

20:04 ibdknox: indeed

20:04 hiredman: ibdknox: could be argued you need a better email client

20:04 Scriptor: the only project I can think of off the top of my head with a forum is a PHP web framework

20:04 ibdknox: hiredman: haha one that auto-syntax-highlights code? :)

20:05 mdeboard`: ibdknox: emacs mail

20:05 Scriptor: emacs os. ftfy

20:05 ibdknox: lol

20:05 mdeboard`: srs

20:05 :)

20:06 * technomancy is so glad he doesn't have to use "forum"s on a regular basis

20:06 Scriptor: hmm, so there is a java netflix lib, but that means now I have to learn interop

20:06 technomancy: that's one of the most annoying things about Android developers; they seem to use PHPbb un-ironically

20:06 mdeboard`: Scriptor: Why?

20:06 amalloy: Scriptor: that's gotta be easier than writing it yourself

20:07 mdeboard`: I ask that question assuming two things: 1. There's a public API for Netflix 2. it's possible to craft HTTP requests in Clojure in such a way that exploits the API

20:07 Scriptor: mdeboard`: I figured a netflix app would be a good first project

20:07 mdeboard`: Scriptor: Oh, I meant using Java interop

20:07 That is a p cool first project

20:08 Scriptor: mdeboard`: oh, because the lib is pure java, so I'd need to use the Java interop to call it from Clojure

20:08 amalloy: I never take the easy route when learning :p

20:11 mdeboard`: Scriptor: Yeah the Java lib is almost certainly the best move in the long run but if you were really averse to it, the Netflix API is pretty straightforward from what I can tell in a 20-sec gloss over.

20:15 gfrlog: Scriptor: write your own and make it somehow enable me to watch streaming video on linux

20:20 mdeboard`: gfrlog: Netflix allegedly has something in the works for that?

20:21 gfrlog: mdeboard`: I'll believe it when somebody tells me it a second time

20:21 mdeboard`: gfrlog: Netflix allegedly has something in the works for that?

20:21 Scriptor: gfrlog: what he said

20:21 gfrlog: ah, I see

20:21 well here's hopin

20:22 hopin: Hey everyone!

20:22 gfrlog: hi hopin

20:22 hopin: Thanks for the intro, gfrlog

20:22 gfrlog: I do what I can

20:22 Scriptor: what

20:22 ah

20:25 hmm, have to apply for a key for each application

20:26 chitsubr: so is lein help supposed to take 5+ minutes to run?

20:26 I downloaded the lein script, chmod +x'ed it and typed lein help, and it is taking forever to run

20:26 mdeboard: chitsubr: It's slow, but not that slow.

20:26 amalloy: lein self-install first

20:27 chitsubr: amalloy: ah so thats what I missed, thx

20:27 amalloy: but it should cope better if you've missed that step, i would think

20:29 Scriptor: when people interop with java libs, what do they do to keep the code from basically becoming java with parentheses, since wrapper functions are discouraged?

20:30 gfrlog: Scriptor: moan and wail

20:31 Scriptor: gfrlog: that's what #clojure's for!

20:32 ataggart: Scriptor: wrapper functions like (defn size [coll] (.size coll)) are discouraged. It really depends on the api one is working with.

20:32 mdeboard: amalloy: How did you say to suggest UI changes for 4clojure?

20:33 amalloy: uh, i didn't really specify. you can mention them here, or open an issue at https://github.com/dbyrne/4clojure/issues

20:34 Scriptor: ataggart: makes sense, I guess I'll write a wrapper when it gets too imperative for my taste

20:35 ataggart: Scriptor: also note that even "java with parentheses" ends up having fewer parens than straight java (e.g., the .. and doto macros)

20:36 mdeboard: amalloy: 1. Put a listener for Ctrl+Return (or whatever) on your "Run" button; since I can't tab out of the REPL box I have to use my mouse to click Run <firstworldproblems> 2. The "Now try %s!" element keeps suggesting the last unfinished problem; I think it would be a bit better if it either automatically suggested the next problem in the list of problems OR if there was a NEXT PROBLEM button.

20:37 Scriptor: ataggart: I know, just using it as a figurative way of saying imperative code that happens to be written in a lisp :)

20:37 amalloy: mdeboard: yeah, the Ace codebox annoys me no end

20:37 stealing all the keystrokes

20:40 mdeboard: for (2), why don't you try forking it yourself? i wrote that feature and iirc it would be pretty trivial to make it link to both of those

20:40 mdeboard: amalloy: I'm not that confident in my clojure-foo

20:46 amalloy: What the hey, I'll give it a go.

20:47 amalloy: mdeboard: sweet. good luck

20:48 you'll feel great when you actually get something done, that's visible in a public clojure project

20:50 Scriptor: heh, just found out *jure names aren't allowed

20:51 hiredman: wuh-pow!

20:58 cemerick: I thought that had been pulled lately?

21:00 mdeboard: How will anyone make an RPG if they can't have names like Abjure and Conjuure?

21:00 Conjure*

21:00 Wait what about Compojure

21:01 Scriptor: mdeboard: I guess it was the original

21:01 and they don't want anything competing with it name-wise?

21:03 technomancy: it's just a restriction on new project generation

21:03 you can work with existing projects just fine

21:03 amalloy: wut. is this an actual thing? someone is saying not to use names ending with jure?

21:04 Scriptor: amalloy: it's built-in to lein, at least

21:06 chouser: just lein, I believe.

21:09 Scriptor: what does it mean when something is 'grandfathered' in?

21:10 mdeboard: Scriptor: A thing being granted an exception to a rule, on the basis that the attribute of the thing that is now forbidden by the rule predated the inception of the rule.

21:10 ibdknox: http://en.wikipedia.org/wiki/Grandfather_clause

21:10 mdeboard: Or yeah.

21:12 Scriptor: mdeboard, ibdknox: ah, thanks, was in relation to https://github.com/pjstadig/leiningen/commit/f4e4c1958d9f9d07d46f7e1c2d3ea11f6b660f72

21:12 mdeboard: amalloy: I'm getting an error while trying to load localhost:8080: "java.util.concurrent.RejectedExecutionException"... I'm operating under the assumption I've left something undone with clojail .java.policy

21:13 amalloy: Or am I missing something.

21:14 ibdknox: Scriptor: yeah, that's just saying that *jure names are no longer allowed, with the exception of compojure

21:14 amalloy: mdeboard: hm. is it possible you just don't have mongodb running? that causes all kinds of weird not-obviously-related exceptions

21:14 mdeboard: Hm I do have it running in a separate term window

21:15 amalloy: And shows several connections/disconnections as I start/stop the dev server

21:15 amalloy: well, that should be fine then. it shouldn't be related to java.policy, but sounds more like an agent issue

21:17 mdeboard: what command are you using to start things up?

21:17 mdeboard: `lein run` in 4clojure/

21:17 and it is starting up ko

21:17 ok

21:17 2011-07-11 16:17:38.572:INFO::Started SocketConnector@0.0.0.0:8080

21:18 but when I try to connect

21:18 that's when it errors out

21:19 amalloy: what if you load a different page, like localhost:8080/problems

21:19 mdeboard: amalloy: same

21:22 wow ps aux|grep mongo yields... interesting results

21:23 amalloy: i don't know what would cause a rejectedexecutionexception

21:23 chouser: iirc, stopping the agents and then trying to use them does that

21:25 amalloy: i wonder if that's related to some issues technomancy had with lein and shutdown-agents, then? i'm using some git checkout of lein from a while ago

21:28 gfrlog: is there a standard way to keep db-auth data in a non-versioned file?

21:30 (such that it is easy to load from clojure)

21:30 amalloy: gfrlog: just add it to .gitignore?

21:31 gfrlog: amalloy: I guess I meant more the easy-to-load-from-clojure part. I.e., would you make it just another source file? or some kind of java properties thing?

21:31 mdeboard: amalloy: Would the ful stack trace help at all? :-\

21:36 technomancy: amalloy: yeah, you can't rely on the agent thread pool to keep the process alive anymore; you need to block if you want to keep non-daemon threads running

21:36 due to Clojure not providing tools for dealing with the agent thread pool correctly

21:37 I have a half-drafted message to the mailing list explaining this that I really should finish

21:39 otherwise a single use of clojure.java.shell/sh will cause the process never to exit (!)

21:40 puredanger has a good explanation of the problem: http://tech.puredanger.com/2010/06/08/clojure-agent-thread-pools/

21:41 mdeboard: technomancy: Hrm I tried out the link, blank page.

21:42 cached http://webcache.googleusercontent.com/search?q=cache:YlxRVd5mJVsJ:tech.puredanger.com/2010/06/08/clojure-agent-thread-pools/+clojure+agent+thread+pools&cd=1&hl=en&ct=clnk&gl=us&source=www.google.com

21:48 cesDave: Hey, does anyone feel like answering a project euler question?

21:48 Should be an easy one...

21:49 hiredman: the answer is "yes it is solvable"

21:50 cesDave: Not the question, question is, why would someone take (range 1 (floor (sqrt n))) when trying to find the factors of n? couldn't there be a factor of n larger than sqrt n?

21:51 guess more of a math question

21:51 mdeboard: project euler is 100% math questions, not programming

21:52 Scriptor: cesDave: think about it, if you have n = 100, pick a number greater than the square root of it that's a factor of 100

21:52 cesDave: 50

21:52 Scriptor: what's 100/50? :)

21:52 jweiss_: is there a function that 'composes' predicates using either and/or?

21:52 cesDave: 2, but 50 is still a factor of n greater than root n

21:52 Scriptor: sure

21:53 but as soon as you know 2 is a factor of 100 you immediately know 50 is as well

21:53 mdeboard: what

21:53 cesDave: true enough

21:54 jweiss_: if you're lookign for primes, once you know one factor, you don't care about the other

21:54 so the smaller one will do

21:54 hiredman: clojurebot: sieve?

21:54 clojurebot: see the genuine sieve of eratosthenes

21:55 hiredman: clojurebot: the genuine sieve of eratosthenes

21:55 clojurebot: the genuine sieve of eratosthenes is http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf

21:55 cesDave: mkay, i'll check it out. thanks!

21:55 sorry for slightly off-topic.

21:55 hiredman: (may include ML)

22:00 chitsubr: if x * y = N, then one of x or y will be less than root(n), since if both were greater than root(n), their product would be greater than n

22:00 scottj: jweiss_: every-pred and maybe some-pred, in clojure 1.3

22:01 Scriptor: chitsubr: right, there's a one-to-one mapping of x<sqrt(n) to factors>n, at least in the natural numbers

22:02 chitsubr: cesDave.. replace less than with "less than or equals"

22:04 cesDave: chitsubr: Yeah, I see that. I'll give that more consideration in terms of the problem I'm looking at. You may have guessed I'm working on project euler 3.

22:04 ataggart: technomancy: did you see any problem with using a shutdown hook to deal with the agent pools?

22:05 cesDave: chitsubr: I'm new to clojure and don't have a math degree so I've got a couple challenges in that regard.

22:09 jweiss_: scottj: thanks - still on 1.2, so i'll just use 'and' :)

22:09 or #(and ...) rather

22:10 or maybe i'll try every? and juxt

22:12 chitsubr: cesDave - right. I wonder if there is a companion site to project Euler that provides some math help for each of the problems.

22:28 Scriptor: man, just adding a jar I downloaded to my lein project seems to require a bunch of hoops

22:28 hiredman: stop downloading jars

22:28 Scriptor: ok :(

22:29 hiredman: find the groupid/artifactid and version, add it to your project.clj

22:29 mdeboard: sigh, I feel as though I'm missing something re: lein again. Once I do "lein new <foo>", when I go into foo/, every lein command I execute is in the 'foo' context, right? e.g. if I do `lein swank` in foo/, when I connect to that connection, all the project's dependencies will be available to me, right? (assuming I did `lein deps`)

22:29 hiredman: let lein download it

22:29 mdeboard: yes

22:31 Scriptor: generally what I do is google "<projectname> maven" to find that info

22:32 mdeboard: hiredman: I have (require 'clojure.contrib.strint) which introduces the `<<` symbol for string interpolation in the src for this project. I have clojure-contrib 1.2.0 in my project.clj. However when i go to my project directory and run e.g. `lein repl` it gives me an "Unable to resolve symbol: << in this context" error message. Am I doing something wrong?

22:33 hiredman: mdeboard: did you load the file that has the require?

22:34 vkurup: \q

22:34 mdeboard: hiredman: I was under the impression it was loaded by lein when I fired up the repl, since it was apparently parsing the file

22:35 Scriptor: hiredman: the repository the jar is hosted on isn't part of the default ones lein looks under, is there a way I can manually edit the pom file or do I need to fiddle with maven?

22:35 hiredman: mdeboard: it wasn't

22:35 Scriptor: have you read the lein readme and looked at the sample project.clj?

22:35 I suggest you do

22:36 technomancy: ataggart: I haven't looked into it enough

22:37 mdeboard: if you want to "land" in a given namespace for every lein repl invocation, set it as :repl-init in project.clj

22:37 mdeboard: hiredman: I see. When I do (use 'change), it returns the same message again

22:37 technomancy: maybe that could be part of the default project skeleton in a future version

22:37 mdeboard: technomancy: I see, i.e. :repl-init foo

22:37 ataggart: technomancy: ok. I added a question to Rich about why the pools use non-daemon threads. Hopefully once we know the full reasoning, we can resolve this. http://dev.clojure.org/jira/browse/CLJ-124

22:37 technomancy: mdeboard: foo.core hopefully

22:37 mdeboard: oh

22:38 technomancy: ataggart: never going to be resolved for 1.2 unfortunately and likely not for 1.3 either =\

22:38 so the hacks and workarounds will be with us forever

22:38 aw geez; that issue has been around since google code days?

22:38 hiredman: ~namespaces

22:38 clojurebot: namespaces are (more or less, Chouser) java packages. they look like foo.bar; and corresponde to a directory foo/ containg a file bar.clj in your classpath. the namespace declaration in bar.clj would like like (ns foo.bar). Do not try to use single segment namespaces. a single segment namespace is a namespace without a period in it

22:39 technomancy: ಠ_ಠ

22:39 hiredman: mdeboard: don't get into a habbit of using single segment namespaces

22:39 mdeboard: ಠ_ಠ

22:40 hiredman: So for package 'change', with change.clj being in ~/change/src/ , for example, I should do :repl-init change.change

22:40 ataggart: technomancy: it might make it into 1.3 if the change I have in mind gets accepted. It wouldn't change any actual behaviour, other than obviating the need to ever call shutdown-agents

22:40 technomancy: ataggart: your optimism is refreshing

22:40 hiredman: mdeboard: no

22:41 there is a reason `lein new` created src/change/core.clj for you

22:41 ataggart: technomancy: it comes back to me when I stop trying to help for a while.

22:41 mdeboard: hiredman: Right, I figured that, but when that dir isn't on my classpath. So I assume di was doing it wrong.

22:42 hiredman: mdeboard: how do you know it is not on your classpath?

22:42 mdeboard: I did `lein classpath`

22:42 hiredman: and 'src' was not on the classpath?

22:43 please picture me here with an eyebrow raised

22:43 mdeboard: src/ yes, but not src/change

22:43 haha

22:43 Cnsider itpictured

22:43 technomancy: hiredman: o_O works well for that

22:43 hiredman: so you (use 'change.core)

22:43 mdeboard: DIdn't seem like classpath was recursive since every change/ subdr was on classpath

22:43 technomancy: mdeboard: each classpath entry should be considered a "root"

22:44 hiredman: technomancy: far too goofy looking, you've seen my eyebrows, they are serious business

22:44 mdeboard: I see

22:44 technomancy: hiredman: true; further exploration of the unicode plane is in order

22:44 mdeboard: hiredman: So, should the code I have in src/change/change.clj go in core instead? core.clj is empty.

22:45 hiredman: mdeboard: change/change.clj (relative to a classpath root) should have a namespace like change.change and can be loaded like (require 'change.change) or (use change.change) or …

22:47 mdeboard: I see

22:49 I've clearly done somehting wrong here, because things which were working last night no longer work :)

22:50 me am no good computer

22:50 Scriptor: hiredman: thanks for the tip, though I'd browsed it enough, :repositories was what I needed (duh)

23:32 ihodes: hiredman: ಠ_ಠ is what you're looking for

23:34 amalloy: i think his eyebrows are likely a lot more formidable than that

Logging service provided by n01se.net