#clojure log - Jun 09 2011

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

0:05 jtszzzzz: dnolen, Here is what I am going for https://gist.github.com/1016032

0:20 dnolen: jtszzzzz: does Submission have a fixed number of fields?

0:20 Scriptor_: Hi everyone

0:21 jtszzzzz: dnolen, I don't intend to use Submission anymore. Sorry for confusion. I just intend to return a map keyed by the provided key on the FieldSpec

0:22 dnolen: jtszzzzz: I think your gist is too much context, a smaller complete example of what you want to do would helpful.

0:22 jtszzzzz: but so far I'm suspecting you don't need a macro.

0:29 jtszzzzz: dnolen, I just added a Generalized.clj to that gist. This should really boil it down to the guts of the problem

0:32 justinko: I just created a new project via lein and added a function. How can I call that function in "lein repl"?

0:33 dnolen: jtszzzzz: so the issue is you need to create those keys based on the # of lists?

0:33 jtszzzzz: yes, and i need the let bindings based on the number of lsits

0:33 and the args into the map based on the number of lists

0:38 justinko .. you need to load your namespace .. do something like (require 'myproject.core)

0:40 then you can navigate to your namespace like this (ns myproject.core)

0:41 justinko: jtszzzzz: that worked, thanks

0:41 jtszzzzz: np

0:41 dnolen: jtszzzzz: https://gist.github.com/1016073

0:43 justinko: jtszzzzz: just found out I can add ":main my-poject.core" to project.clj to automatically hop into that namespace

0:44 jtszzzzz: now is there a "reload" type function that reloads the clj source code?

0:44 for the repl

0:46 technomancy: justinko: (require 'foo.bar :reload)

0:46 jtszzzzz: dnolen, reading this now!

0:48 justinko: technomancy: thanks!

0:52 technomancy: np

0:53 jtszzzzz: dnolen, thanks a lot. That is really nice. I think this will work good for what I am doing!

0:54 dnolen: jtszzzzz: https://gist.github.com/1016088 another version that avoid metadata cleverness.

0:57 jtszzzzz: update the last one for readability (IMO)

0:57 s/update/updated

0:57 sexpbot: <dnolen> jtszzzzz: updated the last one for readability (IMO)

0:58 jtszzzzz: i like it!

1:10 justinko: omg you can define a :test metadata for inline tests? That is awesome.

1:10 do any of you guys actually use it?

1:10 or do you stick with the /test directory?

1:20 dnolen: justinko: I think usage was common in the early days when no tooling, now most people use maven or lein with /test dir.

1:20 cake too

3:29 Dranik: hello all!

3:29 I have a question

3:29 I have the following variable: (def my (ref {:a 1, :b 2}))

3:30 And I wanna a reference from inside the hash-map to my

3:30 justinko: nathanmarz: I just read your interview on geektalk

3:30 Dranik: (dosync (alter my assoc :c my)))

3:31 but this leads to stack overflow

3:31 is there a way to make a cyclic reference {:c my} inside 'my' ?

3:33 nathanmarz: justinko: cool

3:33 hoeck: Dranik: no, not with immutable maps

3:33 Dranik: hoeck: I need a mutable map

3:33 that's why I use ref

3:34 hoeck: Dranik: right, but the map is still immutable

3:34 Dranik: hoeck: is there at least any way to do that? even not idiomatic?

3:34 hoeck: the :c key would have to be a ref too

3:34 Dranik: no, I've tried this also

3:35 probably I should have used a common Java map...

3:37 hoeck: Dranik: having a ref in the map works, but can be kind of clumsy

3:38 Dranik: when you use plain java maps, you loose the threadsafety and other guarantees of clojure maps

3:38 Fossi: probably you need to tell us more about your real problem

3:39 then maybe somebody gcan tell you what would be idiomatic ;)

3:39 what you are currently trying to do sounds like a huge mess to me tbh :>

3:41 hoeck: Fossi: circular datastructures are not that uncommon

3:41 Fossi: yes

3:41 hoeck: Fossi: well, maybe in the land of functional languages

3:41 Fossi: but this instance sounds messy

3:42 esp with mutability and all

3:42 Dranik: Fossi: I'm impoementing a scheme interpreter in clojure using chapter 4 of SICP

3:42 I need this cyclic reference when I create a procedure

3:43 I define a binding for the body of the procedure and add the current environment to it

3:43 hoeck: when I do (dosync (alter my assoc :c (ref my)))), it also throws the same exception

3:44 hoeck: Dranik: the printer throws that exception, because it fails to print your cyclic structure

3:45 Dranik: hoeck: looks like you're right!

3:45 I'll try this...

3:45 hoeck: Dranik: I also have to correct myself, your first approach was correct, you don't have to use a nested ref

3:47 ,(let [my (ref {:a nil})] (dosync (alter my assoc :a my)) (-> @my :a deref :a deref :a deref type))

3:47 clojurebot: clojure.lang.PersistentArrayMap

3:48 Dranik: is there a way to disable the printer?

3:49 hoeck: implementing an interpreter using a circular datastructure does not feel 'right' in clojure

3:50 Dranik: (set! *print-level* 10) on the repl

3:50 Dranik: trying this...

3:50 hoeck: limits printing of nested datastructures to n levels

3:54 Dranik: hoeck: you know what? just disabling the printer solved all the issues! :-)

3:54 thanks a lot!

3:55 hoeck: Dranik: you're welcome

5:34 gilecham: Hmmm, anyone able to shed some light on why:

5:34 (let (vector a 1) a)

5:34 fails stating that "let requires a vector"

5:35 mrBliss`: gilecham: the syntax for let is: (let [a 1] a)

5:49 gilecham: mrBliss`: yes but (vector a 1) should return [a 1] ...

5:51 Chousuke: gilecham: when evaluated

5:51 gilecham: (vector a 1) is a list of two symbols and a number

5:51 evaluating it results in a vector of whatever a is and a number

5:52 s/a is/a evaluates to/

5:52 sexpbot: <Chousuke> evaluating it results in a vector of whatever a evaluates to and a number

5:53 gilecham: Chousuke: so the problem is that, because let is a macro, the call to vector is not evaluated before evaluationg the call to vector?

5:53 Chousuke: gilecham: to put it another way, all code you write must be "literal". If a syntax requires a vector, then you must give it a literal vector.

5:54 gilecham: But when you *generate* code you can of course generate the vector dynamically.

5:54 mrBliss`: gilecham: right (let is actually a special form)

5:55 Chousuke: hm

5:56 gilecham: Drat. I'm trying to write something which will allow me to automatically replace all arguments of a function with new ones generated by a function call on the original. I was hoping to just wrap a let... round the body of my function

5:56 Chousuke: You can do something like this though: &&(let [a 2] `(let ~(vector ['a a]) (do whatever)))

5:57 hm

5:57 mrBliss`: ,`(let ~(vector 'a 1) ~'a))

5:57 Chousuke: how does that inline evaluation wrok?

5:57 clojurebot: (clojure.core/let [a 1] a)

5:57 mrBliss`: Chousuke: ##

5:57 Chousuke: oh right

5:57 damn

5:58 gilecham: note that that ` form only generates the code. to get it to do something, it must be the result of a macro (so that it will be evaluated at runtime) or you must eval it manually

5:58 mrBliss`: gilecham: can you give a small example because I don't really understand

5:58 Chousuke: gilecham: you can probably do that with a macro.

5:58 or you could use the templating facility in core

5:59 gilecham: Chousuke, mrBliss`: Thanks! I thought there was macro magic in here somewhere

5:59 Chousuke: gilecham: this might help http://richhickey.github.com/clojure/clojure.template-api.html

6:02 gilecham: mrBliss`: Intent was to be able to write:

6:02 (defn foo [a]

6:02 (let [a (transform a)]

6:02 (original-body a)))

6:04 Off to read up on templates and return with more questions, thanks again

6:06 terom: Why not just use a higher order function?

8:02 void_: hi there, what is this syntactic sugar please? ->

8:03 fliebel: void_: A thrush, almost at least.

8:03 manutter: Threading

8:03 Let me misuse it, as an illustration...

8:03 fliebel: &(1 (+ 1) (* 2))

8:03 sexpbot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

8:03 fliebel: &(-> 1 (+ 1) (* 2))

8:03 sexpbot: ⟹ 4

8:03 manutter: ,(-> 1 (inc) (println) (inc) (println))

8:03 clojurebot: java.lang.NullPointerException

8:04 manutter: darn, too much abuse

8:04 so much for clarifying the issue

8:04 fliebel: &(macroexpand-1 '(-> 1 (+ 1) (* 2)))

8:04 sexpbot: ⟹ (clojure.core/-> (clojure.core/-> 1 (+ 1)) (* 2))

8:04 fliebel: &(require 'clojure.walk)

8:04 sexpbot: ⟹ nil

8:04 void_: &(doc ->)

8:04 sexpbot: ⟹ "Macro ([x] [x form] [x form & more]); Threads the expr through the forms. Inserts x as the second item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the second item in second form, etc."

8:05 fliebel: &(clojure.walk/macroexpand-all '(-> 1 (+ 1) (* 2)))

8:05 sexpbot: ⟹ (* (+ 1 1) 2)

8:05 manutter: ,(-> (identity 1) (+ 1) (* 2))

8:05 clojurebot: 4

8:06 manutter: The basic idea is that it lets you take (foo (bar (baz x))) and turn it into (-> x (baz) (bar) (foo)), which can be more readable in certain circumstances

8:07 ,(-> (identity 1) (inc) (println) (inc) (println) (inc))

8:07 clojurebot: java.lang.NullPointerException

8:07 void_: oh I see

8:07 manutter: still cant' get that one to work

8:07 o well

8:07 void_: yup, this is what google gave me, nice article: http://debasishg.blogspot.com/2010/04/thrush-in-clojure.html

8:07 fliebel: manutter: println return nil

8:07 void_: &(doc identity)

8:07 sexpbot: ⟹ "([x]); Returns its argument."

8:08 manutter: doh, of course

8:08 fliebel: manutter: You can also skip the identity and enter 1 directly.

8:08 manutter: ,(-> 1 (inc) (inc) (* 2))

8:08 clojurebot: 6

8:08 void_: &(-> (1) (inc) (inc))

8:08 sexpbot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

8:08 manutter: yeah, I was chasing a red herring there :)

8:09 void_: &(-> 1 (inc) (inc))

8:09 sexpbot: ⟹ 3

8:09 fliebel: $(->> (range 10) (map #(* 2 %)) (reduce +))

8:09 &(->> (range 10) (map #(* 2 %)) (reduce +))

8:09 sexpbot: ⟹ 90

8:09 void_: what does it mean if you use ->> instead of -> ?

8:10 manutter: -> comes in handy for things like setting up swing components, where you create something and then do x to it, then do y to it, then do z to it

8:10 fliebel: void_: it inserts the argument at the end instead.

8:10 manutter: The difference between -> and ->> is where the "running" total goes

8:10 raek: void_: (-> x (f a b c)) means (f x a b c), but (->> x (f a b c)) means (f a b c x)

8:10 manutter: let me try again

8:10 fliebel: manutter: Actually, for swing, most actions don't return anything, so you'd use doto.

8:11 void_: this is cool

8:11 manutter: ok, I'm going to just shut up and drink my coffee, it's too early for me still!

8:11 :)

8:12 I don't use -> and ->> much yet, that's probably why I don't understand it as well as I think I do.

8:14 void_: it's amazing how whole source of compojure takes 4 files https://github.com/weavejester/compojure/tree/master/src/compojure

8:14 raek: it helps removing nesting: (into {} (map #(Integer/parseInt %) (remove empty? (line-seq rdr)))) -> (->> rdr (line-seq) (remove empty?) (map #(Integer/parseInt %)) (into {}))

8:15 then you can put each step at its own line, and the code becomes beautiful again...

8:15 manutter: there, that's a much better example

8:17 Yeah, I really like compojure, though the real power behind it is in Ring

8:18 void_: guys, do you think it's a good idea to learn Clojure by building a web application?

8:18 manutter: I'd say so

8:18 especially if your goal is to learn how to write good web apps in clojure

8:19 void_: I still feel very lost in clojure code

8:19 kephale1: in the void so to speak

8:19 raek: one thing that can be fun to do is to build your own chat application and protocol

8:20 void_: oh yeah definitely

8:20 raek: something very simple

8:20 void_: use some sproutcore+websocket for clients

8:20 or backbone.js or whatever

8:20 raek: then you have a little bit of state management too

8:20 void_: yeah I think that will be the next

8:20 I did something like that in node.js

8:21 raek: I was thinking about basic I/O with ordinary sockets, but by all means use whatever knowledge you have to make it fun :-)

8:21 void_: but node.js seems so simple compared to clojure

8:21 raek: yesterday I made hangman game for telnet

8:21 manutter: void_: have you done the 4clojure.org exercises?

8:21 void_: no sir

8:22 manutter: They're a good remedy for the "I feel lost in clojure" syndrome

8:22 void_: now that looks very nice

8:22 I started koans

8:22 manutter: yeah, same idea

8:22 void_: it's amaing how many learnin resources are out there

8:23 manutter: indeed

8:29 void_: by the way "joy of clojure", anybody read it?

8:29 manutter: It's on my bookshelf, I'm partway thru it

8:30 It's not intended as an intro text, I like Clojure In Action for that

8:30 void_: yeah, same feelings here - not an intro text

8:31 manutter: though I just got the "Rough Cuts" version of Clojure Programming, and it's looking pretty good too

8:31 void_: rough cuts, like a beta version?

8:31 manutter: Yeah sort of

8:32 It's what O'Reilly calls their pre-release program

8:32 kephale1: is Raynes' book finished yet?

8:32 manutter: not sure

8:40 void_: hm, so I created a project with lein. And I would like to run REPL on tom of my existing code, is there any easy way to do it?

8:40 oh

8:40 lein repl

8:41 manutter: and if you're using emacs, you can use lein swank and then use M-x slime-connect to run a repl right in emacs

8:41 void_: yeah I'm not

8:41 :)

8:41 textmate

8:41 manutter: Ah

8:41 I've never used that one

8:41 what OS is that/

8:41 ?

8:41 void_: Mac

8:42 manutter: Ah, ok

8:42 I should play with that some time

8:45 kephale1: there was also a recently revitalized lisp GUI for OS X that now uses Clojure and can play fairly nicely with lein… unfortunately the name of it has completely slipped my mind

8:46 manutter: doh!

8:46 kephale1: there is*

8:46 * manutter cackles evilly and fires up google to see what he can unearth

8:47 manutter: Hmm, first google result is Emacs...

8:47 Lemonodor?

8:47 MCLIDE?

8:48 void_: kephale1: I would like to try that

8:48 kephale1: MCLIDE!

8:49 right because it was developed for MCL

8:49 void_: oh ok

8:49 manutter: Might have to give that a whirl

8:49 * void_ downloading

8:49 manutter: First I'm going to stop by and submit the web site to web-sites-that-suck.com tho :P

8:50 void_: If I wanted to play with my code without reloading jvm each time (I use lein run), what is the best way?

8:50 except emacs

8:50 because I'm not in the mood for learning new editor

8:50 manutter: that link is dead :P

8:50 manutter: eh, I probably spelled it wrong

8:50 kephale1: manutter: lol

8:50 manutter: but still

8:50 void_: http://www.webpagesthatsuck.com/

8:51 manutter: That were it! :)

8:53 mrBliss`: void_: are you using https://github.com/swannodette/textmate-clojure ?

8:53 void_: mrBliss`: yes

8:53 but that still doesn't give me repl

8:54 I mean I can execute one line

8:54 which is the same ...

8:54 manutter: omg even the MCLIDE *icon* is that horrible plaid

8:54 mrBliss`: Command-Shift-L loads a file

8:55 kephale1: manutter: at the least I think the project is pretty recently revived… lets hope they're putting all their efforts into the backend ; )

8:55 * mrBliss` is a happy Emacs user

8:55 kephale1: i concur, emacs FTW

8:55 especially when it comes to lisps

8:56 manutter: +1 on both counts

9:02 Vinzent: Is there function combinators somewhere in core or contrib? like (map (fn/and string? empty?) ["" [] ()] => (true false false)

9:03 void_: anybody uses mongo with clojure?

9:03 manutter: Vinzent: there's comp and partial, though from your example I'm not sure that's what you're looking for

9:05 Vinzent: manutter, (fn/and string? empty?) should return the predicate that returns true for things that are strings and empty

9:05 kephale1: Vinzent: i think you'd have an issue with the and since its a macro

9:05 but 1 sec i may have an idea

9:05 Vinzent: same as #(and (string? %) (empty? %)), but shorten

9:06 raek: Vinzent: I think fogus suggested such functions on the clojure dev mailing list a while ago

9:06 hoeck: Vinzent: I'm looking for that too :)

9:06 mrBliss`: found it: http://dev.clojure.org/jira/browse/CLJ-729

9:08 raek: and the discussion: http://groups.google.com/group/clojure-dev/browse_thread/thread/899349c6a9b526e0/10233af5f5f13831

9:08 kephale1: Vinzent: I think you'd have to write a function like the one fogus is suggesting

9:08 but you might be able to use juxt in it

9:09 Vinzent: found the lib: https://github.com/zahardzhan/fn

9:10 kephale1, right, juxt suites me in my case

9:11 but it's more verbose

9:12 kephale1: yeah, but you can use it to write your function which might be something like a comp of a partial and of a juxt

9:12 err that last and is the macro, not the conjunction

9:12 trying to get it to work now

9:22 though i'm avoiding using that fn library...

9:22 ,(every? #(apply (fn [x y] (and x y)) ((juxt string? empty?) %)) (list "" ""))

9:22 clojurebot: true

9:22 kephale1: ,(every? #(apply (fn [x y] (and x y)) ((juxt string? empty?) %)) (list "" '(a b)))

9:22 clojurebot: false

9:23 kephale1: kinda ugly, but you could wrap something like that into a funcion

9:23 function*

9:23 hooray for a reason to use juxt : P

9:26 again there is weirdness in this because i'm not using fn/and but:

9:26 (def predicator (fn [& predicates] #(apply (fn [x y] (and x y)) ((apply juxt predicates) %))))

9:28 someone might have a better idea than the nested application there though

9:30 mrBliss`: (defn every-pred [& preds] (fn [& args] (every? #(apply % args) preds)))

9:31 kephale1: thats the one fogus presented right?

9:32 hrm, yeah mine is far from solving the 0 arg issue

9:32 raek: ,(every? odd? [])

9:32 clojurebot: true

9:35 kephale1: ,(and)

9:35 clojurebot: true

9:35 __name__: Interestin

9:35 *Interesting even

10:25 Dranik: Is there a way to add a library to leiningen project's classpath and not import it into the local maven repository?

10:25 clgv: Dranik: yes, just copy it to your lib directory

10:26 Dranik: and use :disable-implicit-clean true in your project.clj

10:26 Dranik: when does leiningen clean the lib directory?

10:27 raek: Dranik: when you run lein deps, I think

10:27 Dranik: ah, yeah...

10:27 thanks

10:27 raek: Dranik: are you sure the lib is not in Clojars or Maven Central?

10:28 if you make this project publically available, it's much simpler for others if there is an artifact for the dependency

10:28 Dranik: its j2ee5-api.jar...

10:29 fliebel: http://blogs.oracle.com/henrik/entry/moving_to_openjdk_as_the

10:30 kephale1: Dranik: or you can just run your own repository with something like archiva

10:30 raek: Dranik: http://jarvana.com/jarvana/search?search_type=project&project=javaee-api

10:31 Dranik: raek: what's that?

10:31 raek: jarvana?

10:32 Dranik: aha

10:33 raek: jarvana is a search engine for maven artifacts

10:33 Dranik: wow! thanks!

10:33 raek: ...the place to look at for non-clojure libraries

10:34 clgv: raek: great. didnt know that before

10:43 dnolen: fliebel: https://gist.github.com/1016858

10:43 tabling fixed

10:43 fliebel: dnolen: yea, got a notice from jira, great!

10:44 dnolen: fliebel: caveat at the moment is you can't table defns only def + fn because of lexical scoping issue.

10:44 bbl

10:44 fliebel: dnolen: Does htis also mean run is no longer lazy?

10:49 devn: must...find...book: http://www.amazon.com/Art-Prolog-Second-Programming-Techniques/dp/0262193388/ref=reg_hu-rd_add_1_dp

10:49 (for less than 105.00, preferably)

10:52 joly: Am I correct that trampolined functions can't return a vector or map since they implement IFn?

10:53 ,(trampoline (fn [a] [1 a 3]) 2)

10:53 clojurebot: [1 2 3]

10:53 joly: ... I guess not

10:54 ah, parentheses error locally

10:54 mrBliss`: ,(map fn? [(fn []) [] {} #{}])

10:54 clojurebot: (true false false false)

10:56 joly: thanks, I was doing a 4clojure trampoline problem and was using (instance? clojure.lang.IFn r). Totally missed fn?.

10:59 zenoli: devn: AbeBooks has a bunch of copies listed ...2nd ed for ~$40, 1st ed for ~$10.

11:10 anonymouse89: is there a way to exclude a function/macro from being "used" by another ns without explicitly excluding?

11:10 or to rephrase, something like defn- for defmacro?

11:11 fliebel: anonymouse89: If you can add metadata to a macro, you can say ^:private I guess.

11:12 raek: anonymouse89: (defn- foo ...) is the same as (defn ^{:private true} foo ...) and you can use the latter way for macros

11:12 fliebel: raek: Sure? ##(doc defmacro)

11:12 sexpbot: ⟹ "Macro ([name doc-string? attr-map? [params*] body] [name doc-string? attr-map? ([params*] body) + attr-map?]); Like defn, but the resulting function name is declared as a macro and will be used as a macro by the compiler when it is called."

11:13 anonymouse89: fliebel, raek: yes, this works. Thanks!

11:14 * fliebel overlooked attr-map? when scanning fro meta

11:15 raek: I think that basically (defmacro foo [x y] ...) is equvalent to (defn ^{:macro true} foo [x y &env &form] ...)

11:16 hrm, yes. using an attribute map looks prettier: (defmacro foo {:private true} ...)

11:16 anonymouse89: raek: for whatever reason (defn- mymacro ^{:macro true} ... ) gives me a StackOverflow when I call it

11:20 mrBliss`: ,(macroexpand '(defmacro m [args] 1))

11:20 clojurebot: DENIED

11:20 mrBliss`: (do (clojure.core/defn m [args] 1) (. (var m) (setMacro)) (var m))

11:20 so it's not ^{:macro true}, but (.setMacro ..)

11:21 devn: zenoli: thanks!

11:43 dnolen: fliebel: so I think I have an approach that can work for Rel, will be more involved to implement but will address the generality that I want.

11:43 fliebel: dnolen: Coll, I'm all ears :)

11:44 dnolen: fliebel: write a macro that generates the Rel type for all IFn methods, 1-21 args.

11:45 Rel will take 23 params, name meta and 21 fns, possibly initial nil, these are unsynchronized mutable, setters will generate for all o these.

11:45 Clojure will all automatically pack all args past 20 into the rest parameter.

11:45 the 21st arg I mean.

11:48 will need to think about dealing with indexing, but I think this approach can work. I'm interested in a syntax for indexing any arg, as well compound indexes.

11:50 fliebel: dnolen: Okay, so we're now writing a NoSQL db for relations? :)

11:50 dnolen: fliebel: no, some Prologs support this from what I understand.

11:51 fliebel: but yeah, large knowledge bases could be queried efficiently.

11:51 fliebel: So Prolog contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of MongoDB.

11:51 dnolen: fliebel: other way around.

11:52 fliebel: So MongoDB contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Prolog.

11:53 * fliebel doubts the completeness of sexpbot's sed

11:54 fliebel: dnolen: But, sure sounds cool and all. Only... 20 args! I assume Clojure does this for efficiency?

11:55 clgv: fliebel: "Nobody will need more than 20 args!"

11:55 * clgv laughing

11:55 dnolen: fliebel: no Clojure supports arbitrary number of args, so will Rel. it just that anything more than 20 gets packed into a rest arg, so you need to unpack them yourself.

11:56 so only fast path for 1-20.

11:56 fliebel: clgv: Nobody will need more then 5 args 90% of the time, so 20 + varargs seems a weak optimization with a bad sideeffect.

11:56 dnolen: fns that take > 10 args are gross.

11:57 fliebel: dnolen: On the other hand, think about functions like defn and vector...

11:57 clgv: my juxt-map cannot handle varargs yet, since it was too much work and I was content with 8 pairs = 16 args...

11:58 dnolen: fliebel: ?

11:58 fliebel: dnolen: (vector 1 2 3 4) goes over 20 args real quick.

11:58 clgv: fliebel: how often do you specify it manually like this? ;)

11:58 fliebel: clgv: Juxt-map?

11:59 dnolen: fliebel: vector does take arbitrary args, it takes 5 at most.

11:59 fliebel: clgv: Not at all, but I do define functions with more than 20 statements.... maybe.... sometimes

11:59 dnolen: s/doesn/doesn't

11:59 s/does/doesn't

11:59 sexpbot: <dnolen> s/doesn'tn/doesn'tn't

11:59 clgv: fliebel: like juxt but instead of buildin a seq/vec it does build a map with specified keys

11:59 dnolen: ergs

12:17 Vinzent: In midje, how can I say that fn returns approximately some number?

12:18 manutter: Round off the result and say it equals exactly some number

12:19 Hmm, I'm trying to think of a way to make that more specific...

12:20 Ok, let me rephrase that:

12:20 mprentice: how can i get the direct children of a type in a hierarchy created with make-hierarchy?

12:20 manutter: The value x is approximately equal to y if the absolute value of (x - y) is less than some "close enough" factor

12:22 so write your midje test to calculate the absolute value of target number minus actual number, and assert that it is < e (where "e" is the margin of error)

12:23 Vinzent: Yes, I can do it, but the right way is to use roughly:

12:23 (fact (/ 666666.666 13) => (roughly 51282))

12:24 manutter: roughly?

12:24 Oh, is that a midje function?

12:24 Vinzent: Yep

12:25 or, if I want to specify "close enough" number: (fact (/ 666 13.0) => (roughly 51 0.5))

12:25 manutter: well there you go, now I learned something

12:26 Vinzent: Midje is really awesome, isn't it? :)

12:26 manutter: mprentice: I don't know how to get the direct descendants of a type in a hierarchy, but if I had to try, I'd get (descendants h type) and then compare them to each other with isa? to discard the ones that are not direct descendants

12:26 Yeah, I love midje

12:29 mprentice: manutter: hmm, i guess i'm trying to use hierarchy in a way it's not designed for. i want to pre-walk the hierarchy

12:31 dnolen: mprentice: yeah there's parents, but no children.

12:32 manutter: mprentice: can you build your tree structure first, and then use that to build your hierarchy?

12:33 That way they'd be parallel structures, but you could walk the one, and use the other for isa? testing and so on.

12:33 mprentice: i don't need the hierarchy, i was just hoping to use it as an easy way to build a tree

12:34 but i don't think i gained anything by doing that

12:35 manutter: yeah hierarchies are more a tool for describing relationships I think

13:33 void_: hi. I asked this before but: Is there any way to start REPL from inside my program. Something like read-line -> evaluate it in an infinite loop.

13:33 I was just wondering if there is anything that does this.

13:36 manutter: hmm, there's a clojure.repl namespace

13:37 void_: nah there's only things like dir, source, apropos

13:37 manutter: Ah, no I found it

13:37 technomancy: clojure.main/repl

13:37 void_: oh that

13:37 manutter: omg technomancy out-typed me again

13:37 void_: dvorak

13:37 right technomancy? ;)

13:37 manutter: lol

13:37 technomancy: absolutely

13:38 also terseness

13:39 void_: I love how anybody can add examples to http://clojuredocs.org/clojure_core/clojure.main/repl

13:39 or clojuredocs.org

13:42 awesome!

13:43 this (clojure.main/repl)

13:57 timvisher: hey all

13:57 anyone know where I can read some good docs on compojure sessions?

13:58 manutter: compojure sessions or ring sessions?

13:58 timvisher: i suppose that compojure would just be using ring sessions

13:58 i'm not sure

13:58 is there such a thing as compojure sessions?

13:59 better yet, all I'm trying to do is stuff a string into a session

13:59 i found some references to session-assoc

13:59 but i can't find that in the source anywhere

14:01 manutter: all I can find is this: http://clojuredocs.org/ring/ring.middleware.session/wrap-session

14:01 dnolen: timvisher: compojure is really just a routing DSL these days, all session stuff comes from Ring

14:02 manutter: looks like the wrap-session handler just adds a hash map to the :session key on the request object, and you store stuff by putting it in a hash-map your attach to the :session key on the response object

14:02 (but don't quote me)

14:05 timvisher: so my site is defined using the handler/site function

14:05 which auto-wraps sessions around all the routes

14:05 I'm trying to figure out how to alter the session now

14:05 that's where I'm falling down

14:06 manutter: so if I'm understanding the docs correctly, you should be getting a request map that contains a :session key

14:06 Vinzent: timvisher, just get :session key from request map and assoc what you need

14:07 manutter: The :session key on the request is your session data coming in, and then to modify it, create a new map (just use ordinary assoc on the map you get from session) and attach it to a :session key in your response

14:08 timvisher: gotcha

14:08 i think i was expecting things to be more complex. :)

14:08 shame on me

14:08 manutter: well, I'm passing on what I think I've heard, so grain of salt, etc

14:08 but I think that's all there is to it

14:09 If you use Sandbar there's some more complex session handling available

14:09 but Ring is pretty vanilla

14:09 timvisher: gotcha

14:09 Vinzent: iirc you should write your middleware to save session, if your handler doen't modify it

14:10 manutter: I think that the standard wrap-session middleware updates the session data

14:10 The docs say that if you add a :session key to the response, "the session is updated with the new value"

14:11 If I'm understanding that correctly, that should preserve any session values that you did not change

14:13 Vinzent: manutter, may be, I just remember I've read somewhere about it

14:14 manutter: Yeah, I played with it a while ago, I'm trying to remember what I discovered at the time

14:14 but I think I'm somewhere in the ballpark anyway

14:14 timvisher: is the referrer sent when a form posts to a url?

14:15 amalloy: timvisher: should be, but you also shouldn't really rely on it

14:15 timvisher: here's the big picture of what i'm trying to do.

14:16 I've got a long page with a bunch of small elements, I'd like to

14:16 send a post to a route, and then focus the result of the function

14:16 called there when I return to the previous page

14:16 i'd like to return to whatever url they were on previously, as well.

14:16 although at the moment i just redirect to root

14:17 amalloy: timvisher: a popular way to do the latter is to post to /myform?backto=somepage

14:18 timvisher: amalloy: brilliant. :) don't know why i didn't think of storing the window.location in the form

14:18 ok, so that solves that problem

14:19 then, i can store the title in the session on the way back and focus it there

14:19 awesome

14:53 lawfulfalafel: how do you find out the size of a list?

14:53 amalloy: count

14:54 &(map count ["string" '(some list) [1 2 3 4]])

14:54 sexpbot: ⟹ (6 2 4)

14:54 amalloy: lawfulfalafel: ^

14:59 lawfulfalafel: thanks you amalloy

15:05 pdk: does anyone know if clojure bit-shift-right is equivalent to java >> or >>>

15:05 iirc >>> sets the high order bits to 0

15:05 TimMc: ,(bit-shift-right -1)

15:05 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$bit-shift-right

15:05 TimMc: ,(bit-shift-right -1 5)

15:05 clojurebot: -1

15:07 TimMc: Looks like sign-extend to me.

15:09 pdk: ,(type (bit-shift right 255 1))

15:09 clojurebot: java.lang.Exception: Unable to resolve symbol: bit-shift in this context

15:09 pdk: ,(type (bit-shift-right 255 1))

15:09 clojurebot: java.lang.Integer

15:10 zakwilson: Am I understanding correctly that I can't do variable capture in a Clojure macro?

15:11 pdk: you should be able to

15:12 it has a reader macro for gensym after all

15:12 dnolen: zakwilson: you can, ~'foo

15:12 ,`(foo)

15:12 clojurebot: (sandbox/foo)

15:12 dnolen: ,`(~'foo)

15:12 clojurebot: (foo)

15:13 zakwilson: dnolen: thanks

15:14 pdk: not using gensyms where they would ordinarly be called for usually throws an exception.

15:14 pdk: ,~'foo

15:14 clojurebot: java.lang.IllegalStateException: Var clojure.core/unquote is unbound.

15:15 pdk: wait durr

15:28 is there a changelog for 1.2.1

15:34 miwillhite: @technomancy, one time I was in here asking how to get environment variables…when you told me you prefixed the function call with a comma (it was something like ",(System/getenv)")…was that a typo, or does the comma mean something when used that way?

15:35 Chousuke: miwillhite: on this channel , invokes clojurebot

15:35 raek: miwillhite: comma is whitespace in clojure. it is also the prefix clojurebot listens to for code evaluation

15:35 miwillhite: ah okay, thanks :P

15:36 ,(+ 1 1)

15:36 clojurebot: 2

15:36 miwillhite: sweet

15:36 ampleyfly: ,_

15:36 clojurebot: java.lang.Exception: Unable to resolve symbol: _ in this context

15:36 TimMc: ,,,,,,

15:36 clojurebot: EOF while reading

15:39 amalloy: is there a good/standard way to implement IFn by hand rather than with (fn …)? I've written (reify IFn (invoke [this] …)), and that works for 0 args. if i call it with any args, it throws an AbstractMethodError. in some ways that's fine since i don't want to allow any args, but it would be nice if it threw an arity exception instead

15:39 i can proxy AFn, but it's my understanding that you should stay away from proxy if you can help it

15:40 to avoid an XY issue: i'm doing this because i want to implement IDeref as well as IFn

15:43 hiredman: A nasty way to do it would be to use a Var

15:44 actually, well, the fullfils what you said in the most pointless way

15:46 amalloy: well. the more i poke at it the less certain i am that implementing IFn is really a good idea anyway

15:49 lawfulfalafel: can someone help me with this code? http://pastebin.com/AytnsLps

15:49 dnolen: amalloy: I would write a helper macro to throw ArityException on the other arities. I'm planning on implementing IFn and I see there's a lot of boilerplate that could be abstracted away.

15:49 lawfulfalafel: I don't really get how I am supposed to keep the numbers I am generating

15:49 bhenry: lawfulfalafel: you're not thinking functionally

15:50 hiredman: yeah, a deftype+helper macro for replacing AFn is just waiting to be written

15:50 lawfulfalafel: bhenry: so where is the error in my thinking?

15:51 raek: lawfulfalafel: use let instead of def inside functions

15:51 def is not for local variables

15:51 bhenry: ,(doc let)

15:51 clojurebot: "([bindings & body]); Evaluates the exprs in a lexical context in which the symbols in the binding-forms are bound to their respective init-exprs or parts therein."

15:52 raek: lawfulfalafel: have you learned about loop and recur?

15:54 lawfulfalafel: also, in a functional solution, you will typically not have any calls to 'do', 'doseq' or any other construct that is made for side-effects

15:55 lawfulfalafel: example of a loop in Clojure to sum all numbers between 0 and x: (loop [acc 0, i x] (if (zero? i) acc (recur (+ acc i) (dec i))))

16:05 amalloy: lawfulfalafel: also line 15 you need whitespace after the +

16:14 naeu: is there a simple way of listing a given object's fields/methods?

16:14 raek: naeu: show

16:15 naeu: raek: thanks

16:15 now i need to figure out how to unfreeze emacs

16:15 i tried this in a slime repl: (println (vec (.getMethods (class f))))

16:15 and it totally froze up

16:15 raek: clojure.contrib.repl-utils/show

16:16 naeu: killing emacs seems cruel

16:16 raek: naeu: I think you can press C-c C-c in the repl

16:16 naeu: raek: yeah, i've tried that

16:17 raek: so it froze emacs itself, and not the swank server?

16:18 naeu: raek: yup

16:18 raek: i even killed the swank server and emacs is still frozen

17:08 raek: has anyone successfully managed to use autodoc lately?

17:09 if I use the standalone jar with java -jar, it chokes on my usage of clojure.java.io (seems like autodoc evals the code in clojure 1.1)

17:10 if I add it as a dev-dependency, it fails because clojure-contrib 1.1.0-master-SNAPSHOT does not exist anymore

17:11 void_: so I was thinking .. Android is running on JVM. Clojure produces JVM bytecode. Can you create Android apps with Clojure?

17:11 I mean, yes you can (I googled that), but does anybody do it?

17:12 raek: void_: it is possible, but quite slow currently. I hear they are working on it: http://dev.clojure.org/display/design/Android+Support

17:15 offby1: void_: actually, Android doesn't run on the JVM. Google wrote their own, incompatible VM called "Dalvik".

17:15 In theory, however, it is probably possible to add a Dalvik backend to the Clojure compiler

17:15 void_: oh yeah I now recall that they have their own

17:16 so Google have their own Java compiler too?

17:20 ohhh ->/->> is cool

17:20 (->>

17:20 (mongo/fetch :expenses)

17:20 (map (fn [e] (:title e)))

17:20 )

17:20 this is such beautiful code

17:21 raek: void_: if you tend to use 'map' with anonynous functions a lot, consider using 'for' instead

17:21 Chousuke: void_: why not just (map :title)?

17:21 raek: (for [e (mongo/fetch :expenses)] (:title e))

17:21 void_: thanks guys thanks ;)

17:22 raek: eh, what Chousuke said ;-)

17:22 void_: Chousuke: didn't know you can do that

17:22 Chousuke: it's one of the little awesome features that Clojure has :P

17:22 raek: but seriously. the autodoc deps seems to have been broken for half a year now.

17:23 is the conclusion that nobody document their code?

17:23 or have everyone switched to Marginalia?

17:23 (Marginalia is very neat, but not what I want in this case)

17:25 ohpauleez: raek: I use Raynes' autodoc AND marginalia in my stuff

17:25 and generate both

17:25 Raynes: ohpauleez: I'm fine with just using marginalia, fyi.

17:26 raek: ah, now Raynes' version works for me. wonder what I were doing wrong.

17:26 solussd: ,(->> 3 (* 3) (/ 4) (* 5)) ;it can make ugly code too!

17:27 clojurebot: 20/9

17:27 Raynes: I have a version of autodoc?

17:27 Cool.

17:27 raek: Raynes: thanks for fixing it

17:27 [org.clojars.rayne/autodoc "0.8.0-SNAPSHOT"]

17:27 Raynes: You're welcome. I'd tell you how I did it if I could remember actually doing it.

17:27 I seem to recall doing something minor to it for my cake autodoc plugin.

17:41 void_: hmm why doesn't "\n" make a newline?

17:42 \newline neither

17:42 oh I got it

17:42 I wouldn't pass it to println

18:00 lawfulfalafel: just out of curiosity, why does the empty list evaluate to true?

18:01 It seems like it would be useful for recursive functions that are being passed a list

18:01 or maybe that's just my n00b opinion

18:01 dnolen: lawfulfalafel: you have (seq foo) for that. only nil and false are false-y thank heavens.

18:02 raek: lawfulfalafel: the rules for truthiness is that nil and false are falsey, everything else is truthy

18:02 that something empty can be non-nil allows for more laziness

18:03 otherwise a lazy-seq producing function would have to force the first element to check whether it should return nil or not

18:51 zakwilson: Is there a built-in inverse of coll? (like CL's atom)

18:52 hiredman: coll? doesn't just test for collections, it tests for IPersistentCollection

18:53 Raynes: (comp not coll?)

18:53 hiredman: so java collections will all return false

18:53 etc

18:54 amalloy: zakwilson: no, mainly because clojure has a fuzzier dividing line. it's not "lists vs everything else"

18:56 zakwilson: I'd be safe ignoring Java collections in this case, but is there a generic test for single values versus collections that works on everything?

18:57 hiredman: it really depends on what you are doing with it, there is no generic always safe test

18:58 if you are writing a macro and dealing with clojure forms coll? and (comp not coll?) are good enough

19:01 zakwilson: That's exactly what I'm doing.

19:01 hiredman: I figured as much

19:02 I imagine it being part of some elaborate system of macros

19:02 and then I sigh and try to think of something else

19:03 choffstein: Hey all -- I have a question. I have a situation where I am building html content using hiccup with different functions. In on area, I have something like "[:li {:id "myTab"} (fn-to-render-content arg1 arg2)]". My issue is that I need fn-to-render-content to return two vectors, not a vector of two vectors. I was thinking about constructing some sort of macro to "unwrap" a vector and return the individual elements ... like "(u

19:03 [1 2 3 [4 5]]))" becomes "1 2 3 [4 5]"

19:03 Is that possible?

19:04 hiredman: sounds horrid, but zakwilson is a macro writer, so he can help you

19:05 zakwilson: No elaborate system of macros, but the macro does call a multimethod to mangle its arguments.

19:07 choffstein: you could (apply u [1 2 3 [4 5]])

19:07 Well, not u(nwrap), but whatever function it is you want to call on 1 2 3 [4 5]

19:09 choffstein: zakwilson: I don't want to apply a function though

19:10 something more like "[a b c (unwrap [d e f])]" would return "[a b c d e f]"

19:10 hiredman: not possible

19:10 amalloy: choffstein: that's not possible

19:11 choffstein: boo

19:11 amalloy: and for good reason

19:11 choffstein: alright. can't know unless you ask, right? :)

19:11 zakwilson: ,(flatten [1 2 3 [4 5]])

19:11 clojurebot: (1 2 3 4 5)

19:11 zakwilson: that's about as close as it gets

19:12 choffstein: Yeah ... but not quite what I am looking for unfortunately. It is alright.

19:12 I'll figure it out

19:12 amalloy: wait, choffstein, you want to use this for hiccup?

19:12 zakwilson: It can be done in Common Lisp, but Clojure doesn't have multiple return values.

19:12 choffstein: yes

19:12 amalloy: just return (list [ret1…] [ret2…])

19:13 hiccup renders seqs by expanding them into the parent element, roughly

19:13 choffstein: amalloy: hiccup seems to be running into issue having a parent element with no tag

19:13 amalloy: choffstein: with a *list* parent element? vectors are not lists

19:13 choffstein: doh.

19:14 amalloy: choffstein: try (html [:ul '([:li 1] [:li 2])])

19:14 i think that ought to return a :ul with two children

19:15 choffstein: list worked ... vector didn't. doh.

19:15 feeling stupid.

19:15 thanks :)

19:15 amalloy: choffstein: that's because vectors are for introducing html elements, and you don't want to introduce an html element ;)

19:15 choffstein: that makes a completely reasonable amount of sense :)

19:40 gigamonkey: So everybody seen Fogus's interview with Hickey? http://www.codequarterly.com/2011/rich-hickey/

19:41 brehaut: gigamonkey: and the companion interview with abelson? ;)

19:42 hiredman: I sure hope everyone has seen it, it's been online for *hours*

19:44 gigamonkey: brehaut: yeah, you can read than one too. ;-)

19:44 hiredman: come on, we're on Internet time here.

19:44 hiredman: sorry

19:45 it's been online for *beats*

19:45 gigamonkey: heh.

19:46 brehaut: hah

19:46 devn: gigamonkey: i have now

19:48 offby1: what devn said :)

19:53 "optional type hints", eh? Cool

20:17 "Hammock-Driven Development". I'd sign up for that.

20:19 Moominpapa: I imagine I'll get a "doc" answer for this one, but is there a function in the standard library equivalent to (fn [coll­ f] (redu­ce #(ass­oc %1 %2 (f %2)) {} coll)­)?

20:21 brehaut: (into {} (map (juxt identity f) coll))

20:22 hiredman: wrong

20:22 brehaut: figures

20:22 hiredman: Moominpapa: not really

20:22 ,(let [a {:a 1}] (zipmap (keys a) (map inc (vals a))))

20:22 clojurebot: {:a 2}

20:23 Moominpapa: I guess group-by does the opposite...

20:23 hiredman: brehaut: pardon me, I think I misread that

20:24 brehaut: hiredman: no problem

20:27 Moominpapa: Thanks.

20:32 technomancy: clojurebot: uh oh

20:32 clojurebot: Excuse me?

20:33 Moominpapa: It uses leiningen... :)

20:37 * offby1 sets his hair on fire

20:52 * __name__ extinguishes offby1's hair.

20:52 __name__: Nice nick, btw :)

20:53 offby1: there's an offbyone out there, too; we run into each other occasionally and duel

20:54 __name__: Heh

21:36 mattb[]: howdy

21:37 brand new to clojure, lisp, and functional programming in general (raised on C)

21:37 I was looking at different fibonacci implementations and found one using data recursion rather than function recursion:

21:38 (def fib-seq (lazy-cat [0 1] (map + (rest fib-seq) fib-seq)))

21:38 two questions about this:

21:38 amalloy: mattb[]: yeah, brehaut likes that one

21:39 mattb[]: 1. does evaluating (rest fib-seq) and fib-seq in the map reevaluate the sequence for *each*, or once the lazy sequence is evaluated does it cache the values?

21:39 amalloy: lazy seqs are cached

21:39 mattb[]: 2. how does the functional community look at problems like this; prefer data recursion, or prefer function recursion?

21:39 alright cool, I figured

21:39 amalloy: mattb[]: the definition there is one that's popular in haskell

21:39 mattb[]: something about data recursion seems ridiculously elegant to me

21:39 brehaut: data recursion like that is good in haskell, less good in clojure

21:40 mattb[]: ah

21:40 brehaut: because its hard to define that in a non-global way

21:40 s/hard/awkard/

21:40 sexpbot: <brehaut> because its awkard to define that in a non-global way

21:40 mattb[]: gotcha

21:40 dnolen: brehaut: I disagree.

21:40 mattb[]: that style is natural in Clojure as it has neither TCO nor Haskell laziness.

21:40 amalloy: in clojure i like ##(take 15 (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])))

21:40 sexpbot: ⟹ (0 1 1 2 3 5 8 13 21 34 55 89 144 233 377)

21:41 * mattb[] scoops brain back in

21:42 mattb[]: I've come to appreciate s-expressions pretty quickly, but I still have a crazy hard time wrapping my head around code

21:42 amalloy: $google clojure rosetta-code fibonacci

21:42 sexpbot: First out of 61 results is: Fibonacci sequence - Rosetta Code

21:42 http://rosettacode.org/wiki/Fibonacci_sequence

21:42 brehaut: dnolen: im weak on binding-fu and vars, but i dont know how to create a definition of fib like the recurvsive one mattb[] showed that doesnt have a global var (and the head-retention that goes along with it)

21:42 amalloy: mattb[]: an explanation of my code is there

21:43 mattb[]: awesome thanks amalloy

21:43 brehaut: dnolen: what have i got wrong ?

21:43 dnolen: brehaut: you can name anon fns.

21:43 brehaut: dnolen: im not sure if we are talking about the same thing?

21:43 oh

21:44 actually we are and i misread the definition

21:44 dnolen: mattb[]: lazy-seqs are particularly powerful as they can be mutually recursive.

21:45 mattb[]: so this wikipedia article claims the haskell-inspired fib to be "more elegant"; what makes you prefer the iterate version amalloy?

21:45 amalloy: mattb[]: well, if someone on rosettacode says it's more elegant, it must be true...

21:46 mattb[]: oh lol this isn't wikipedia.. duh

21:47 amalloy: mattb[]: the way the haskell version is implemented on rosetta code involves holding the head of the lazy sequence, so would eventually run out of memory

21:47 mattb[]: "map first ;; throw away the "metadata" (see below) to view just the fib numbers" it doesn't explain this; what's the deal with metadata?

21:47 ahh ok

21:47 that's what was meant by head retention

21:47 amalloy: dnolen is probably right in that it could be implemented better

21:48 mattb[]: when i wrote that, i meant something like "turn each [prev, next] pair into just one integer"

21:48 feel free to edit in a way as to make that clearer

21:48 mattb[]: ah k

21:50 this does seem a lot more sane than the "more elegant" version

21:51 amalloy: it's an acquired taste, i'm sure

21:53 mattb[]: thanks for the help guys

21:55 by the way, in the doc for iterate: "f must be free of side-effects" how is this explicitly enforced? are builtins flagged for whether or not they allow side effects?

21:55 brehaut: mattb[]: its not

21:55 danlarkin: it should read "f _should_ be free of side-effects"

21:56 mattb[]: k

21:57 brehaut: mattb[]: an effects tracking system is requires a lot of complexity (see also: haskell) akin to (or part of) a type system

21:57 mattb[]: aye

21:58 am I right in seeing haskell as more of a research language than for practical use?

21:58 brehaut: mattb[]: http://www.codequarterly.com/2011/rich-hickey/ search for "I think Haskell is a fantastic" and read the next 3 paragraphs

21:58 dnolen: mattb[]: not true these days, people using haskell for pratical things.

21:58 brehaut: mattb[]: not really.

21:58 mattb[]: its practical once you master it, its just not easy to master

21:59 mattb[]: ah

21:59 dnolen: mattb[]: also possible to get verification for Clojure via Datalog/Prolog, I'm working on that.

21:59 mattb[]: nice link brehaut

22:03 something I was having a hard time finding is in situ algorithms in functional languages; the quicksort example I saw for clojure specifically mentioned that "this isn't really quicksort since it's not in situ"

22:03 what would something like that look like?

22:04 brehaut: it would look like the imperative example that had been mangled a little, and it would operate on a transient

22:04 in the future it might operate inside a pod, and in haskell it would exist inside an effectful type context.

22:04 mattb[]: is this a case where such an algorithm would just be a poor choice for a functional implementation?

22:05 brehaut: it depends?

22:06 mattb[]: I mean, do you reap the memory benefits of an in situ algorithm if it's not in situ?

22:06 dnolen: mattb[]: remember Clojure's not didactic about purity, you can implement quicksort on a mutable array if you like.

22:06 mattb[]: aye, I'm thinking more from a general functional context though

22:06 dnolen: functional languages like OCaml and Standard ML have similar escape hatches.

22:06 mattb[]: still trying to wrap my head around how you guys get anything done without state :p

22:06 brehaut: mattb[]: we use state when we need to

22:07 clojure excels at handling state

22:07 mattb[]: I see

22:07 dnolen: mattb[]: Clojure probably has more state management facilities than pretty much any language out there except Haskell.

22:07 brehaut: as dnolen said, theres mutable arrays, we have access to javas mutable collections, transient versions of clojures collections, and a grab bag of great reference types

22:10 mattb[]: imperitive state is also trivially modelable as a bunch of functions that take a 'world' and return a new 'world, and through the power of higher order functions, you can abstract that away

22:12 you might have encountered these in C# or F# as Linq or Workflows if you've lived in dotnet land

22:13 mattb[]: yep, coming from C# actually

22:13 brehaut: C# is actually a pretty decent halfway point to functional languages

22:13 its just the average stdlib that lets it down

22:13 (ie, all the old stuff)

22:14 mattb[]: the biggest hurdle so far is remembering what data structures look like in clojure; I keep trying to pass an integer from a vector to map lol

22:14 the whole lisp thing is eating my brain

22:14 brehaut: i dont follow

22:15 mattb[]: just misinterpreting what I'm actually passing around

22:16 is that "ants" demo from rich hickey still a good example to learn from? I know a few minor things changed syntax-wise

22:16 (e.g. vec in lieu of apply vector)

22:17 brehaut: theres also a few fairly significant library additions that make the ode a bunch cleaner

22:17 and defstruct has been deprecated

22:17 mattb[]: aha

22:17 that's good to know

22:17 brehaut: it uses (dorun (for …)) or something (could be doall, or have a map or something) where doseq would be better

22:18 and it uses send-off in place of (for example) future from memory

22:19 mattb[]: dorun retains the head like doall?

22:19 brehaut: nah one of them doesnt

22:20 mattb[]: k

22:20 brehaut: but doseq should generally be your first choice for side-effects on sequences

22:20 not least of all because it has full comprehension notation supported

22:21 doall retains the head btw, dorun discards

22:21 mattb[]: yeah

22:22 found a couple list messages about them

22:23 by the way, can fn [_] be anonymized? I found I couldn't get it to infer an argument in an anonymous function without using it

22:23 (by anonymous I mean #, maybe that's just sugar?)

22:23 brehaut: by fn [_] you mean a functio nthat ignores its argument?

22:24 mattb[]: yea

22:24 brehaut: you cant use the #() reader form to abbreviate it no

22:24 mattb[]: k

22:24 brehaut: but constantly might be what you are after

22:24 &(map (constantly :a) (range 10))

22:24 sexpbot: ⟹ (:a :a :a :a :a :a :a :a :a :a)

22:25 amalloy: &(map #(do % :a) (range 10))

22:25 sexpbot: ⟹ (:a :a :a :a :a :a :a :a :a :a)

22:25 brehaut: amalloy: yuk :P

22:25 mattb[]: haha

22:25 amalloy: not recommended, but fulfills the stated requirements

22:26 mattb[]: what does evaluating the arguments even do?

22:26 amalloy: ?

22:27 mattb[]: if you did that to a list with a function in it, would it call the function?

22:27 (the do %)

22:27 amalloy: no

22:27 it's a no-op, although it might not get entirely compiled away

22:27 mattb[]: k

22:28 when was defstruct deprecated? it's not documented as such in the api ref

22:28 brehaut: it was deprecated when defrecord was introduced

22:30 http://clojure.org/data_structures#Data%20Structures-StructMaps

22:30 the word 'depreciated' isnt used

22:30 mattb[]: indeed

22:30 I disregarded that note before

22:30 brehaut: "Note: Most uses of StructMaps would now be better served by http://clojure.org/datatypes."

22:30 mattb[]: so defstruct was a hashmap and defrecord is an actual java class with final fields?

22:31 brehaut: defrecord is still a map

22:31 but yes, its backed by a custom class

22:32 consider them an intermediate feature of the language though, you dont need them

22:33 mattb[]: so in hickey's example, (defstruct cell :food :pher) would be better served by defrecord or a different structure entirely?

22:34 brehaut: 'better' how?

22:34 for performance, yeah a record

22:34 but a map would suffice

22:34 mattb[]: in terms of deprecation/more "functional"

22:34 k

22:34 brehaut: neither is 'more functional'

22:35 structs were just maps with certain keys given a performance optimisation

22:35 mattb[]: aye

22:36 brehaut: the clojure idiom is to write your code in terms of the abstraction, in this case maps (with keyword keys)

22:36 and maps are the general case of that

22:37 with structs and records as implementation details

22:37 mattb[]: gotcha

22:37 brehaut: thats good, cause i made a meal of the typing ;)

23:08 dnolen: man I love macros

23:10 brehaut: dnolen: any particular reason today?

23:11 dnolen: brehaut: implementing IFn deftype in pure Clojure, lots of crazy boilerplate eliminated.

23:11 brehaut: oh true cool

23:12 ifn has a million arg variations right?

23:12 dnolen: yeah

23:47 amalloy: psh. i'm sure careful consideration went into each line of AFn.java

23:48 brehaut: im sure it was either a hand manging emacs chord or an arcane jumble of vim

23:50 dnolen: AFn.java would drive anyone screaming to macros.

23:51 amalloy: dnolen: so you might think, but look at MouseAdapter in awt

23:52 mattb[]: hahaha

23:52 just looked up afn.java

23:53 I'd like to believe someone did this by hand

Logging service provided by n01se.net