#clojure log - Oct 15 2011

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

0:02 amalloy: ThreeCups: it may help to understand that use is a combination of require/refer

0:03 ibdknox: ,(doc refer)

0:03 clojurebot: "([ns-sym & filters]); refers to all public vars of ns, subject to filters. filters can include at most one each of: :exclude list-of-symbols :only list-of-symbols :rename map-of-fromsymbol-tosymbol For each public interned var in the namespace named by the symbol, adds a mapping from the name of the var to the var to the current namespace. Throws an exception if name is already mapped to somethin...

0:03 amalloy: require causes code to be loaded, and refer creates aliases in your current namespace to already-loaded symbols

0:03 ibdknox: wow

0:03 self-referential

0:03 napping: carllerche: The name just sounded like something for making xss attacks

0:03 carllerche: heh… it's the opposite :P

0:16 ThreeCups: ibdknox, amalloy: thanks. I'm slowly wrapping my head around this :)

1:21 bsteuber: is it possible to execute js for simulating a button click with clj-http?

1:26 jedahu: strange clojurescript behaviour

1:26 (- 1) ; => 1

1:26 clojurebot: 0

1:26 jedahu: the defn of - in cljs.core is correct

1:28 napping: bsteuber: I've seen some java libraries that could

1:28 jedahu: (cljs.core/- 1) ; => 1

1:29 ibdknox: the math ops are inlined now

1:29 jedahu: ibdknox: I am using v0.0-838-g567be71

1:29 just pulled a minute ago

1:30 napping: HttpClient (which clj-http wraps) claims not to: http://hc.apache.org/httpcomponents-client-ga/primer.html

1:30 ibdknox: jedahu: https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/core.clj#L57

1:30 bsteuber: napping: until now I just found selenium but it controls an actual browser and thus might be slow for data mining

1:32 thanks anyways - gotta leave..

1:32 napping: I think it was over 10 years ago, but I remember something that included a dom and a javascript interpreter (is Rhino that old?)

1:32 jedahu: ibdknox: thanks. in that case, is there a negation function/macro lying around?

1:32 napping: Xerces and Rhino, IIRC

1:33 jedahu: or can - be fixed to behave like cljs.core/- ?

1:33 ibdknox: jedahu: (- 0 1)

1:33 ,(- 3)

1:33 clojurebot: -3

1:34 ibdknox: ,(- 0 3)

1:34 clojurebot: -3

1:34 jedahu: ibdknox: fair enough

1:34 napping: Ah, HtmlUnit

1:34 is there any way to leave a message?

1:40 amalloy: napping: in irc, you mean?

1:40 napping: on clojurebot, I was thinking

1:40 amalloy: $mail napping lazybot will take messages for you

1:40 lazybot: Message saved.

1:41 napping: $mail bsteuber The library was HtmlUnit. It seems to still be active

1:41 lazybot: Message saved.

2:02 Raynes: $mail napping I wouldn't rely on that though. lazybot isn't very aggressive and will only NOTICE people when they have messages. If they don't have NOTICEs set up to direct to whatever channel they're in, it may be a while before they see it or they may never see it at all.

2:02 lazybot: Message saved.

2:03 Raynes: amalloy: Now, let's see if he ever actually gets that message. Should be fun.

2:04 scottj: lame on github's search page they have languages split into popular and everything else and common lisp and scheme are both in the popular section and clojure is in the everything else despite clojure having a higher popularity ranking on github

2:05 Raynes: scottj: I hate how far down I have to scroll in the dropdown in gists.

2:05 amalloy: every pixel an insult

2:06 ibdknox: seriously.

2:06 we should petition

2:06 scottj: Raynes: looks like you can type Clojure in the drop down

2:08 Raynes: scottj: Still, it's blasphemy.

2:53 FrankL: How can I update the clojure version counterclockwise uses to 1.3.0?

2:54 I tried googling, but couldn't really find a guide

2:55 mikera: FrankL works for me just by including the Clojure 1.3 jar in the build path rather than the 1.2 version (I do this with Maven usually, but I think it works by just editing the standard build path as well)

2:56 FrankL: thanks mikera, i'll try that

3:01 hm, just changing the build path and refreshing the project doesn't work

3:02 although i haven't changed the clojure-src.jar

3:03 amalloy: chouser: i just looked at the new, 1.3 impl of doc. i can't see a reason for not quoting the first half of the if-let - it means that if i did, say, (defn print-&-doc [] (doc &)), that would print the docs once at compile time instead of every time the function is called

3:05 FrankL: ah, nevermind, i only changed the src attachment the first time, now it works

3:05 thanks mikera!

3:05 mikera: np! glad you got it to work, these things can be fiddly sometimes.......

3:15 anyone had luck getting Pallet to work with Clojure 1.3?

3:16 Raynes: dakrone: You wouldn't happen to be around, would you?

3:37 todun: When defining my function using defn, I want to pass a list as a parameter. The syntax seems to be to use square brackets for parameters. However the syntax for lists are parentheses(circular brackets). do I do this: defn function-name [a-list] ...) or do I do defn function-name2 (another-list) ...)? I'm new to clojure so sorry if this sounds silly.

3:38 mikera: todun just do (defn my-fun [listname] .....)

3:38 brehaut: todun: the arguments vector is independant of the types of the variables you pass

3:38 todun: When I call my function in the REPL, do I do (function-name [1 2 3]) or do I do (function-name2 (1 2 3 4)) ?

3:39 mikera: the former is best

3:39 todun: mikera: brehaut ok. that is a bit confusing. I see that there are seqs, lists, vectors, sets. All with different syntaxes for defining them.

3:39 mikera: (1 2 3 4) won't work since it will try to apply "1" as a function to the arguments 2, 3 and 4 which is probably not what you want....

3:40 you can do (my-fun '(1 2 3 4)) though if you like, which will pass a list rather than a vector

3:40 brehaut: todun: you almost never define lists in your code; they are more frequently used at the macro level

3:40 todun: mikera: so parens are like function scopes all the time in clojure?

3:40 brehaut: todun: no, they are sometimes macros or special forms

3:41 todun: brehaut: is clojure doing type inferencing then? if so, how does it infer type if its structure is not specified?

3:41 brehaut: todun: and they represent many list like things when printed to the repl (seqs, cons, lists etc)

3:41 todun: it does type inference for purposes of avoiding reflective calls in interop but its a dynamically typed language

3:43 amalloy: todun: i think you are barking up the wrong tree. (foo bar) always indicates "call the function foo with argument bar", unless (a) foo is a macro itself, or (b) that list is surrounded by a macro or special form that dictates otherwise

3:43 todun: brehaut: I just read up on macros and it seems they're like interfaces in java or python's modules.

3:43 brehaut: ,(map (juxt class pr-str) [(list 1 2 3) (map inc [0 1 2]) (cons 1 ())])

3:43 clojurebot: ([clojure.lang.PersistentList "(1 2 3)"] [clojure.lang.LazySeq "(1 2 3)"] [clojure.lang.Cons "(1)"])

3:43 amalloy: sorry, they are nothing like interfaces or modules though

3:43 brehaut: todun: not at all

3:43 todun: macros allow you to effectively write compiler plugins

3:44 todun: namespaces are roughly analogous to pythons modules and protocols are roughly analogous (but way better) than javas interfaces

3:44 todun: amalloy: brehaut uhm. ok.

3:44 brehaut: I've not seen protocols yet.

3:45 not sure if I've seen macros.

3:45 amalloy: macros are a concept that no other languages really have

3:45 brehaut: todun: you dont need them yet

3:45 todun: brehaut: ok.

3:45 amalloy: (no other non-lisps, that is)

3:45 todun: I'll keep writing my recursive methods and come back if I fall into a conceptual rut...

3:46 , '(1 2 3)

3:46 clojurebot: (1 2 3)

3:46 todun: cool!

3:46 amalloy: todun: brehaut's summarization of macros as compiler plugins is good, and a useful way to think of things. you're using macros all the time, you just don't know about it

3:46 brehaut: you should be trying to learn how _not_ to be writing recursive methods

3:46 todun: amalloy: ok.

3:46 brehaut: how so?

3:46 brehaut: todun: functional programming includes lots of abstractions that take care of the recursion for you; eg, map reduce filter etc

3:46 reduce is a particular recursive pattern

3:47 amalloy: &(if-let [x 1] (inc x) :no-such-thing)

3:47 lazybot: ⇒ 2

3:47 amalloy: &(macroexpand '(if-let [x 1] (inc x) :no-such-thing))

3:47 lazybot: ⇒ (let* [temp__3586__auto__ 1] (if temp__3586__auto__ (clojure.core/let [x temp__3586__auto__] (inc x)) :no-such-thing))

3:47 todun: amalloy woah.

3:48 amalloy: I've just done some reading on TOC, lazy seq, regular recursion.

3:48 brehaut: tadah!

3:48 mikera: :-) todun you should probably ignore that stuff for now!

3:48 amalloy: todun: if-let is a pre-built "plugin" for the compiler that turns "function calls" that start with 'if-let into slightly more useful code

3:48 todun: amalloy: trying to implement a bunch of problems using all these techniques.

3:48 mikera: ok.

3:49 amalloy: heh, well. using every technique all at once will just lead to a soupy mess, probably

3:49 todun: brehaut: Arthur C Clarke comes to mind here...

3:49 mikera: not that it's not useful, but there is a lot to take in at once... took me a couple of months before I got comfortable with macros....

3:50 todun: amalloy: how does let work? also, how does letfn work? I couldn't understand what it was quite doing in the examples I looked at.

3:50 mikera: ,(let [x 10] (* x x ))

3:50 clojurebot: 100

3:50 todun: mikera: ok. I'll avoid it for now. but I have a feeling I'll need it when I reach concurrency.

3:51 brehaut: todun: have you joined 4clojure?

3:51 todun: brehaut: nope. I can join?

3:51 mikera: yeah you will need it, but i'd suggest getting the basics nailed first, especially the stndard syntax, higher order functions etc.

3:51 4Clojrue is a great way to start!

3:52 todun: ,(reverse (1 2 3 4))

3:52 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

3:52 amalloy: todun: www.4clojure.com

3:52 mikera: ,(reverse '(1 2 3 4))

3:52 clojurebot: (4 3 2 1)

3:52 todun: ,(reverse [ 1 2 3 4])

3:52 clojurebot: (4 3 2 1)

3:52 mikera: you need the ' to make a list......

3:52 todun: ,(reverse [1 2 3 [1 2 3]))

3:52 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: Unmatched delimiter: )>

3:53 todun: why does the second one give an error?

3:53 mikera: unmatched brackets, you want:

3:53 amalloy: ([[])) doesn't balance

3:53 mikera: '(reverse [1 2 3 [1 2 3]])

3:53 ,(reverse [1 2 3 [1 2 3]])

3:54 clojurebot: ([1 2 3] 3 2 1)

3:54 brehaut: also, if you are reversing a vector (rather than a sequence or list) you might want rseq instead of reverse

3:55 todun: brehaut: that's why I asked my earlier questions. I want a list specifically.

3:56 brehaut: todun: why? its not common to want a list specifically in clojure

3:56 todun: , '(1 2 3 (1 2 3))

3:56 clojurebot: (1 2 3 (1 2 3))

3:56 todun: brehaut: ok.

3:57 amalloy: I have corresponding brackets, why doesn't it balance?

3:57 Raynes: [[] <-- Note the lack of second ].

3:57 amalloy: your, uh...your statement is untrue

3:58 todun: Raynes: amalloy yes. thanks.

3:59 ,(reverse '(1 2 3 '(1 2 3)))

3:59 clojurebot: ((quote (1 2 3)) 3 2 1)

3:59 todun: I was warned about clojure and its brackets.

4:00 brehaut:

4:00 clojurebot: Huh?

4:00 brehaut: you prefer to type more of them?

4:00 or you'd prefer only parens?

4:01 todun: brehaut: indifferent.

4:02 mikera: Clojure usage of brackets is actually very logical, it's just different from C-like languages. I usually need less in Clojure than I do in Java for the same code.

4:03 todun: mikera: I'm yet to find that out or not.

4:03 brehaut: todun, python's equivalent of your expression above is [1,2,3,[4,5,6]][::-1] which is equally brackety, and has additional punctuation not needed in clojure

4:05 todun: brehaut: I'm not decrying clojure. just saying that I've really not done much in it to say one way or another. In fact, these will be my first non-example clojure code I'll be writing.

4:05 :)

4:09 mikera: http://www.infoq.com/presentations/Clojure-in-the-Field is a good video for some of this stuff

4:11 todun: mikera: thanks.

4:13 mikera: other things is 4Clojure (http://www.4clojure.com/), well worth doing 20-30 of these problems. a nice bonus is that you get to see how other people solved the probelms too......

4:14 brehaut: mikera: or 80-90…

4:14 i dont have a problem. i could quit whenever i want

4:15 amalloy: brehaut: i have a stash of four problems i haven't solved yet, for when the cravings get really bad

4:15 brehaut: amalloy: ive got mostly involved or mathy ones left

4:16 amalloy: well, me too. i actually left them unsolved cause i wasn't really interested :P

4:16 brehaut: hah :)

4:16 we cant all be chouser i guess

4:21 102 has taught me i dont know the string ns at all well enough

4:21 todun: is there a way to kill the currently running command in the REPL without quitting the REPL?

4:22 brehaut: it depends

4:22 what repl ?

4:23 todun: lein repl

4:23 brehaut: i think you might be out of luck

4:25 todun: brehaut: ok. thanks.

4:27 amalloy: brehaut: wait till you get to 117. some of the solutions will make you wonder if the authors have ever seen a library that isn't about strings

4:28 brehaut: amalloy: that looks like a PITA

4:28 and i am fearful of how you would do that as a strings problem

4:28 amalloy: yeah, my solution is pretty awful

4:28 amcnamara has a good solution that makes sense, but chouser and youz do some WEIRD string stuff i can't understand at all

4:28 brehaut: haha

4:29 i bashed out a game of life solution last night

4:29 i went and looked at some of the solutions

4:30 mine is the 4yo with crayons version

4:30 amalloy: *laugh*

4:30 brehaut: all the basic elements are there, but its really crude

4:31 youz solution confuses the crap out of me

4:33 amalloy: (- -1 w) is something that almost seems like it can't make sense

4:34 brehaut: hah yeah

4:34 its not an idiomatic construction thats for sure ;)

4:35 Raynes: youz is God.

4:42 amalloy: he's more like loki. a Trickster

4:43 brehaut: haha excellent

5:06 archaic: i rebound ; to 'paredit-open-paren .. best decision ever

5:08 amalloy: archaic: so you can't write any comments? i prefer swapping the "shift-ness" of numbers and symbols; 9 isn't such a hard key to reach for, and i can still pepper my everyday speech with semicolons

5:10 archaic: comments is C-; now since i use alot less than paren

5:10 amalloy: the important thing is you're customizing, though. don't stick with inferior tools, and don't listen to strangers like me who tell you your setup is silly

5:12 and there's a nice parallel with java/c which is covered with semicolons

5:25 todun: I'm getting errors I can't quite understand when I do this http://pastebin.com/TiAg30gZ

5:26 raek: todun: (defn z n ...) --> (defn z [n] ...)

5:26 todun: raek: but n is just a number, does it need [n} ?

5:26 raek: but the cond clauses don't make much sense

5:27 todun: *[n]

5:27 raek: todun: yes, a function can have more than one argument

5:27 todun: raek: uhm ok. thanks.

5:28 raek: just like you need the ()s in java: public static void main(String args[]) ...

5:28 todun: raek: that does make sense. thanks.

5:28 raek: todun: cond takes alternating conditions and expressions. you have 3 forms on the middle line and only one on the last

5:29 todun: raek: uhm. I don't quite follow.

5:29 raek: if n is even, is cond going to return z or (/ n 2)?

5:30 todun: raek: alternating conditions as in conditions that don't match?

5:30 raek: oh. so it's not sequential?

5:30 raek: meaning it does not do the first, second then last?

5:31 raek: it is sequential. lets say you have (cond c1 e2 c2 c2 c3 e3 :else e4)

5:31 if it check c1 first. if it's true, cond will evaluate and return e2

5:31 *it will check

5:31 if c1 was false, c2 is checked

5:32 if c2 is true, then e2 is evaluated and returned

5:32 so cond is like "if (..) .. else if (..) .. else if (..) .. else"

5:33 what I

5:33 I'm confused about is "z (/ n 2)"

5:33 if (even? n) returns true, then z is evaluated and returned

5:34 if (even? n) returns false, (/ n 2) is the new condition to check

5:34 which doesn't make much sense, since it's a number

5:34 did you mean (z (/ n 2))

5:34 todun: raek: ok.

5:35 raek: if I have a function.

5:36 a function to me is when I use defn, and I call it within its definition(recursion), do I put a space between the function name and the arguments?

5:36 raek: todun: a function call is always wrapped in a pair of parens

5:36 todun: what I did was call z(/ n 2) is this illegal?

5:36 raek: yes, that's not clojure syntax

5:37 todun: raek: I see. the example I was following for cond didn't have a function call but just literals. I projected that case to function calls.

5:37 raek: so that's why I get a strange result for that case. thanks.

5:37 raek: if you for instance say (+ 2 z (/ n 2)), that would mean "take the sum of 2, the function z, and the expression (/ n 2)". i.e. z is not called

5:38 (+ 2 (z (/ n 2))) means "take the sum of 2 and what you get when you call z with (/ n 2)"

5:39 todun: raek: ok.

5:39 raek: todun: http://pastebin.com/LYS2XBYV

5:40 so in clojure, the parenthesis are never optional

5:41 todun: raek: I get an error when I try this http://pastebin.com/EBCevmWi

5:41 illegalArgsExcetion.

5:41 thanks for the least.

5:41 *list

5:41 archaic: (+ 1 2 3)

5:41 clojurebot: *suffusion of yellow*

5:41 raek: todun: you didn't fix the (defn z [n] ...) problem

5:42 and the :else line has an error

5:43 todun: raek: sorry I did. I just didn't change the pastebin right.

5:43 let me repost

5:43 raek: what you should have is (cond c1 e2 c2 e2 :else e3)

5:43 todun: raek: ok.

5:43 raek: but what you have is (cond c1 e1 c2 e2 (:else e3))

5:44 sorry, it should be "c1 e1" in the first line

5:44 todun: oh. so :else is a function?

5:44 I thought it was a keyword?

5:44 raek: no, it's a keyword

5:44 which is a value

5:45 :else evaluates to :else, since keywords are self-evaluating (like numbers)

5:45 archaic: is (dorun (map ..)) idiomatic to force a map for side-effects?

5:45 todun: http://pastebin.com/kfxN5inh

5:45 raek: and the rule for conditions in clojure is that false and nil are falsy, and everything else (including keywords) are truthy

5:46 amalloy: clojurebot: who taught you (+ 1 2 3) is *suffusion of yellow*, anyway?

5:46 raek: archaic: either that or (doseq ...)

5:46 clojurebot: I don't understand.

5:46 todun: raek: uhm. ok.

5:46 raek: so :else is a condition that is always true

5:46 todun: raek: like a default value.

5:47 raek: you could have written true instead of :else there, (as you would do in common lisp) but it's ideomatic to use :else in clojure

5:47 todun: or a java pass or perhaps continue

5:47 raek: todun: yes, it's the last catch-all case

5:48 todun: but the parentheses around :else and (z (+ (* 3 n))) shouldn't be there

5:49 those parentheses will make that whole thing the condition and then there's no expression for it (since the contents of 'cond' will now be an odd number of forms)

5:49 todun: but I thought it ought to be around functions, like z?

5:50 raek: but you don't want to unconditionally call :else with the result of (z (+ (* 3 n))), right?

5:51 'cond' is a special form, so it doesn't work like a function call

5:51 it's a macro that gets translated into a bunch of ifs

5:51 todun: raek: uhm ok. et me do some debbuging.

5:52 raek: (cond c1 e1 c2 e2 c3 e3) --> (if c1 e1 (if c2 e2 (if c3 e3 nil)))

5:52 the if special form has the syntax (if <condition> <then expression> <else expression>)

5:53 todun: this is what you function should look like: http://pastebin.com/94trLBhS

5:54 note that in clojure whitespace and newlines are not part of the syntax

5:54 only the parentheses determine the structure of the code

6:18 todun: raek: uhm. ok.

6:20 raek: instead of using z, I can usee recur, so it does TOC?

6:30 is there a way to check for duplicates?

6:31 llasram: Duplicate which?

6:32 archaic: there are functions frequencies and distinct that may do what you need

6:35 todun: llasram: (duplicates? '(1 1 2 2 3))

6:36 archaic: ok. let me read up on those.

7:11 what is the value of an empty list?

7:11 or rather, how to test if a list is empty?

7:11 opqdonut: ,(doc empty?)

7:11 clojurebot: "([coll]); Returns true if coll has no items - same as (not (seq coll)). Please use the idiom (seq x) rather than (not (empty? x))"

7:11 opqdonut: also, you can compare to '()

7:12 which is slightly different

7:16 todun: opqdonut: thanks.

7:16 opqdonut: I tried '() but got an error.

7:16 opqdonut: sorry. take that back.

7:16 I was trying ()?

7:25 Borkdude: I'm trying to push to heroku, how do I get a 'local' jar up there?

7:25 Question was also asked on the Clojure google group: http://groups.google.com/group/clojure/browse_thread/thread/4045276f24444a69

7:32 todun: how to find the head of a list in clojure? is there like a term called head ? also is the only way to find the nest element (head (next a-list))? thanks.

7:33 archaic_: (first [1 2 3])

7:33 archaic: (rest [1 2 3])

7:33 todun: archaic_: thanks.

7:34 ,(first [1 2 3])

7:34 clojurebot: 1

7:45 daniel__: thats a vector...

7:45 ,(peek '(1 2 3))

7:46 clojurebot: 1

7:46 daniel__: for a list

7:48 todun: ,(if (= (compare (first [1 2 3]) (first (rest [ 1 2 3])) ) 0) (remove (first [1 2 3]))

7:48 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

7:48 todun: why is this wrong?

7:49 I thought if takes only condition & expression.

7:49 or no?

7:51 raek: if takes one condition and two expressions

7:51 and remove takes a function and a collection

7:51 ,(remove even? [0 1 2 3 4])

7:52 clojurebot: (1 3)

7:52 raek: and you can use (= x y) instead of (= (compare x y) 0)

7:53 todun: raek: ok. let me refine it. thanks.

7:58 reak: if I want to know the result of remove in the following, how do I get it?

7:59 ,(if (= (first [1 2 3]) (first (rest [ 1 2 3])) ) (remove (first [1 2 3])))

7:59 clojurebot: nil

8:04 raek: todun: that call to remove doesn't make any sense

8:04 todun: can I do assignment in clojure?

8:04 raek: no sense in what way?

8:04 raek: well, you usually don't do it for computations

8:04 (assignments)

8:05 you can use let, which introduces a name for a value (but doen't allow you to reassign it)

8:05 ,(doc remove)

8:05 clojurebot: "([pred coll]); Returns a lazy sequence of the items in coll for which (pred item) returns false. pred must be free of side-effects."

8:05 raek: remove take two arguments, and you only pass it one

8:05 also, remove does not do what I think you think it does

8:06 if you want a new sequence where the first element is missing, use rest

8:06 todun: raek: uhm. ok. let me rework it.

8:06 raek: todun: also, that code snippet returns nil since the condition is false

8:07 (if condition then-expr) = (if condition then-expr nil)

8:07 todun: raek: ok.

8:07 raek: the else branch defaults to a constant nil if you don't supply it

8:08 todun: it's better to think of functions as thing that receives some values and make a new value, rather than a thing that changes stuff

8:09 you can think of the expression (rest coll) as a name for "coll, but without the first element"

8:09 todun: ,(if (= (first [1 1 3]) (first (rest [ 1 1 3])) ) (remove (first [1 1 3]) [1 1 3]) )

8:09 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

8:10 raek: todun: remove does not take an element as the first argument. it takes a predicate

8:10 todun: raek: ha. uhm. ok. I misread that then. sorry.

8:10 raek: (let [coll [1 1 3], x (first coll)] (remove (fn [element] (= element x)) coll))

8:10 ,(let [coll [1 1 3], x (first coll)] (remove (fn [element] (= element x)) coll))

8:10 clojurebot: (3)

8:11 raek: you can write that predicate as #(= % x) or even #{x}

8:11 todun: raek: I see.

8:12 raek: if I want to yield the list after the remove, how do I do so?

8:13 raek: remove yields the list

8:13 todun: in particular, the output is (3) but I expect it to be (1 3)

8:13 raek: todun: but filter removes *all* occurances where the predicate matches

8:13 todun: I dont use filter.

8:14 raek: todun: if you just want to get a list without the first element (whatever it is) use "rest"

8:14 todun: sorry, remove

8:14 todun: raek: ok. let me try that.

8:14 raek: filter does the opposite (keep the elements where the predicate return true)

8:14 ,(rest [1 2 3 4])

8:14 clojurebot: (2 3 4)

8:15 todun: raek: ha yes. the imperative mind-set trap was not letting me see that optimization. thanks.

8:16 raek: in functional languages, the expression is the building block, not the statement

8:16 and you describe values, rather than side-effects

8:17 todun: raek: how do I use let to ensure I'm working with the modified list?

8:17 raek: if returns a value too (namely the value of either the then-expression or the else-expression, depending on the value of the condition)

8:17 ,(let [rest-of-the-list (rest [1 2 3 4])] .... use rest-of-the-list-here ...)

8:17 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: .... in this context, compiling:(NO_SOURCE_PATH:0)>

8:18 raek: todun: you just give a name to the result of the if or the rest call or whatever and then use that name in another expression

8:19 ,(let [foo (rest [1 2 3 4])] (reverse foo))

8:19 clojurebot: (4 3 2)

8:19 raek: ,(reverse (rest [1 2 3 4]))

8:19 clojurebot: (4 3 2)

8:20 todun: raek: is this functional, this internal side-effecting that I'm proposing?

8:20 raek: what side-effect?

8:20 let is side-effect free

8:20 todun: raek: giving names and passing them like you did.

8:21 raek: to give names to values is indeed functional

8:21 todun: raek: uhm. ok.

8:21 raek: you cannot change the values themselves in clojure

8:21 so [1 2 3] will always be [1 2 3]

8:21 (let [original [1 2 3], changed (rest original)] ...)

8:22 inside the let, original still refers to [1 2 3] and changed refers to (2 3)

8:23 so the standard libary functions don't actually change collections, they return new variants of the old values

8:23 and the old values are still available

8:23 todun: raek: um. ok.

8:23 , (if (= (first (name [1 1 3])) (first (rest name)) ) (rest name) )

8:23 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to clojure.lang.Named>

8:24 todun: do I have to use the square brackets?

8:24 raek: what are you doing with the 'name' function here?

8:24 ( ) means call a function

8:24 todun: making it [1 1 3]

8:24 raek: (name [1 1 3]) <-- what do you want this to do?

8:25 todun: I want it to be called by first, rest

8:25 (if (= (first name)) (first (rest name)) ) (rest name) )

8:25 name = [1 2 3]

8:25 raek: then you need to let it first

8:26 "name" is also a function in the standard library

8:26 ,(let [name [1 1 3]] (if (= (first name) (first (rest name))) (rest name) "something here"))

8:26 clojurebot: (1 3)

8:28 todun: raek: ok. thank.

8:29 raek: also "let" is a special form, so (let ...) is not a function call

8:29 todun: raek: special form?

8:29 raek: it's hard-coded in the compiler

8:30 (let ...) has special rules for how the "..." is interpreted

8:31 so you don

8:32 't evaluate the [name [1 1 3]] thing. the compiler looks at it and emits code that stores the [1 1 3] gives it a name

8:32 todun: raek: I see. just like the way TOC works.

8:33 *TCO

8:37 when I write this function to remove duplicates, I get the following error: not connected.

8:37 http://pastebin.com/gk2ftEnP

8:38 and it really an error per se, it is just that when I compile, I get the message splash at the bottom.

8:42 I just realized it was referring to the swank server closing.

8:43 When I try to reconnect, it keeps saying Connection closed. How is this possible?

8:43 I thought the server was on my machine?

8:56 I'm trying to do a reversal of a list. Even if the input is a list of lists, I want this nesting to be reversed. To this end, I use recur. But I don't think I have the logic right. Any comments, critiquing will be appreciated: http://pastebin.com/qYete3fb

9:39 Borkdude: Is it possible to push to heroku and let the server find jars based on pom.xml instead of project.clj?

9:40 For a Clojure project that is of course

9:53 Solved it through a push to clojars instead...

9:53 (the local but now not local anymore jar problem)

10:12 Is it possible to remove one of your groups and jars from clojars?

10:15 I want my jar to be in the group org.clojars.borkdude

10:15 so the group twitter-utils may be removed

10:17 (so I don't get in the way of someone else maybe one day wanting this name for a project)

10:55 kylpo: Woop woop! Finally have some time to start learning clojure this weekend :)

10:56 Borkdude: :-)

11:10 Hmm. What is supposed to be the outcome of (= (list) [])

11:12 I suppose lists and vectors are compared by elements, regardless of their type

11:15 floatboth: is lein install supposed to be like mvn install:install-file? because only the latter works properly :( I mean, with subprojects, I want to install them to the local repo and then lein deps on the main project should get them from it. But it only works after mvn, not lein install

11:16 Borkdude: have you tried lein localrepo?

11:16 https://github.com/kumarshantanu/lein-localrepo

11:17 floatboth: yeah

11:18 it requires version and group/artifact id, it's kinda the same thing

11:18 but looks like shell magic should work, like lein localrepo coords *.jar | xargs lein localrepo install

11:18 Borkdude: floatboth: lein localrepo worked for me

11:18 floatboth: what's the point of lein install then?

11:19 Borkdude: dunno :)

11:23 tomoj: floatboth: does the bit after defproject for the project you ran `lein install` on match the group/artifactid?

11:25 floatboth: hmm

11:26 looks like it's ok, "installing this.jar into ~/.m2/repository/group/artifact/this.jar"

11:29 aaah, got it, lein sub was running it on the main project too before installing subprojects

12:00 duck1123: Generally speaking, if I get reflection warnings from a 3rd party library, then that's not really my problem, right? I'm trying to eliminate some of the reflection in my library and am wondering if I should be concerning myself with reflection in dependencies

12:09 Squeese: Ok, so reading pragmatics clojure book and "installing examples dependancies" with lein, it's spitting me maven error messages, supposedly not finding a package - where can I browse these packages and fix it? Is there a reposatiry somewhere?

12:10 dnolen: duck1123: the only problem is suboptimal interop perf from the dependency. You should let the lib author know.

12:13 Squeese: Yah, I sent mail, it's a beta release of the book

12:16 oh well, http://build.clojure.org/ didnt make me any smarter, guess I'll butter up the patience :)

12:23 Ok, so, I cant use (require 'deps) since the lein deps spits errors, can I modify "dep path" myself or maybe enter repl with a file loaded (wanting to try the examples)

12:25 daniel__: (ns evolve.core

12:25 sry

12:25 (nth (iterate #(doto (str ((fitness-fn target) %) " " (evolve % (fitness-fn target))) println) source) generations))

12:26 can anyone tell me why this prints the fitness an increasing number of times for each iteration?

12:26 it should be like: 100 blah; 200 blak; 300 blay; but instead its more like 100 blah; 100 200 blak; 100 200 300 blay;

12:30 robermann: daniel: I think the problem is using iterate

12:30 ,(doc iterate)

12:31 clojurebot: "([f x]); Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"

12:31 Borkdude: Squeese: what book is this?

12:31 Squeese: Pragmatic programmers, Programming Clojure

12:33 daniel__: robermann: yeah, i see

12:33 hmmm

12:34 robermann: (interleave [100 200] ["blah" "blak"])

12:34 ,(interleave [100 200] ["blah" "blak"])

12:34 clojurebot: (100 "blah" 200 "blak")

12:39 robermann: or maybe you could use the repeatedly function

12:45 daniel__: robermann: maybe, ill have to think it through

12:46 with repeatedly can i pass back what is returned as % like with iterate?

12:46 in fact, nvm

12:46 that defeats the point

12:47 i might be able to work it in to my evolve method somehow as a side effect

12:47 duck1123: daniel__: can't you just map over the results and print them outside of the iterate? That way you're keeping that iterate fn side effect free?

12:49 daniel__: duck1123: im not sure i know what you mean

12:49 Squeese: ok, this.. is.. sexy.. why? I have no idea, its just.. sexy: (def sexy {:key "val"}) and then (:key sexy) or (sexy :key)

12:49 is this general Lisp or Clojure specific?

12:50 duck1123: daniel__: instead of printing inside the iterate function, pass that seq to a mapping form that does the print. The laziness should still give you the progress you'r looking for

12:53 Bronsa: Squeese: afaik only clojure has it

12:53 Squeese: kk

12:54 robermann: daniel__: i think duck1123 is suggesting something like: (map #(println %) (range 1 10))

12:55 daniel__: the range being the iterate

12:55 ok, think i get it

12:55 let me try

12:55 robermann: yes

12:55 duck1123: robermann: exactly.

12:59 Is there something I can pass to lein to put it into a strictly offline mode? If I'm maxing out my internet connection, then lein deps will take a long time to complete even if it's not apparently fetching snapshots.

13:01 daniel__: (nth (map #(doto (str ((fitness-fn target) %) " " %) println) (iterate #(evolve % (fitness-fn target)) source)) generations))

13:01 works :) just looks a mess

13:02 duck1123: daniel__: that's when -> and ->> start to become your friend

13:04 daniel__: duck1123: i guess now would be a good time to learn what they do then :)

13:04 and commit it to memory this time :p

13:05 robermann: daniel__ BTW, are you working on anything like http://www.pawfal.org/dave/blog/2011/10/evolving-musical-bytecode-3/ ?

13:06 duck1123: (-> (fitness-inner-fn) (iterate source) println (nth generations))

13:07 daniel__: no robermann, but it looks interesting

13:08 robermann: ok, i was just curious too, because recently I read http://www.pawfal.org/dave/blog/2011/10/evolving-musical-bytecode/ , where do exists a "fitness" function

13:09 daniel__: im just evolving a string into another string...an experiment to learn clojure really

13:10 duck1123: daniel__: are you converting the problem from your work in a different language, or is this something all new?

13:10 daniel__: duck1123: all new

13:11 although it would be a lot simpler in another language at the moment

13:11 duck1123: I've been converting my large ruby application at work to clojure. It's difficult to translate an existing process sometimes

13:11 daniel__: i like clojure but i think you have to know it well to get the benefits

13:11 duck1123: Of course now I curse the days I have to work in Ruby

13:12 It's really a progression of things clicking

13:12 daniel__: yep, i also came from ruby and i find it much easier to think of how to solve a problem in terms of ruby than clojure

13:12 but its v early days

13:13 robermann: I translated stack traces/source code into music, just to stay on strange topics: www.codesounding.org

13:14 daniel__: i now think i want a map to map the map :p i want to add line numbers

13:14 duck1123: I find that I'm very much spoiled by Clojure's correct concurrency without having to think about it when working in Ruby. I'm always saying "Well, if this was in Clojure, I'd just ... and be done"

13:15 ->> puts the output of the previous form into the collection spot of the next form

13:15 (->> coll (map fn1) (map fn2) (filter pred1) first)

13:16 daniel__: ,(expmacro -->)

13:16 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: expmacro in this context, compiling:(NO_SOURCE_PATH:0)>

13:16 daniel__: ,(expandmacro -->)

13:16 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: expandmacro in this context, compiling:(NO_SOURCE_PATH:0)>

13:17 duck1123: ,(macroexpand '(->> coll (map fn1) (map fn2) (filter pred1) first))

13:17 clojurebot: (first (clojure.core/->> (clojure.core/->> (clojure.core/->> coll (map fn1)) (map fn2)) (filter pred1)))

13:17 duck1123: (first (filter pred1 (map fn2 (map fn1 coll))))

13:18 daniel__: ok

13:18 duck1123: I believe comping those 2 map fns may be better than 2 maps, but you get the idea

13:18 daniel__: btw, in this case is there an opposite of macroexpand? it should be fairly easy to take an expression and turn it into -->

13:19 ->>*

13:19 duck1123: well, turning things into a macro is really more for your benefit than the compiler.

13:20 I'd love to see someone write something for clojure-mode though

13:20 daniel__: yes, but to make sure i dont make any mistakes moving things around

13:21 duck1123: unit tests :)

13:21 daniel__: :)

13:21 duck1123: anyway, I'm off. good luck

13:21 daniel__: alright, thanks

13:23 robermann: interesting stuff, you wrote that in clojure?

13:24 robermann: no, it was in java, it started on 2006

13:24 but the "sonification" core is now delegated to Max/MSP patches

13:24 or Pure Data

13:25 the more interesting java library was jsyn

13:26 zilti: I've seen this piece of code in a presentation (defn describe [[head & tail]] (body here)) and wondered what would happen if it's possible to split the arg in more than two parts. It turned out that [[first & second & tail]] doesn't work. So is the [[x & y]] only syntactic sugar for head and tail?

13:27 robermann: What did you write? I joined too late but it sounds interesting

13:29 Borkdude: zilti: how about (defn describe [[a b & tail]] [a b tail])

13:30 robermann_: zilti: we were speaking of www.codesounding.org

13:31 zilti: Borkdude: Thanks :)

13:31 robermann_: having some spare time it would be interesting to add a plugin for using overtone

13:32 Borkdude: zilti: & means: all the rest of the args

13:32 zilti: robermann_: That framework sounds like a fun, interesting project. :)

13:32 robermann_: yes, it started as a joke / challenge

13:33 zilti: Borkdude: I'm very new to Clojure. I knew & usually means "varargs" but I didn't know the syntax of [[ ... ]]

13:33 Borkdude: np

13:33 robermann_: zilti: but someone used similar techincs for software metrics: http://sourceforge.net/apps/wordpress/codesounding/2010/08/27/translating-software-metrics-into-music/

13:34 zilti: robermann_: The second example sounds damn futuristic

13:35 robermann_: Does it only work with Java?

13:36 robermann_: the second example is based on JSyn: http://www.softsynth.com/jsyn/

13:36 you can also "pipe" the event to Max/MSP patches

13:36 (or pure data)

13:36 via UDP packets

13:37 Squeese: why is the quote used here: (require '[clojure.string :as str]) how is the vector list intepreted?

13:37 Borkdude: Squeese: if the quote wasn't there you'd have to quote every single element (except :str) in the vector

13:38 ~[a b c]

13:38 Squeese: so its the same as (require ['clojure.string :as 'str]) ?

13:38 clojurebot: bartj: it's not broken. Unless you know the performance hit there is actually a problem, I'd recommend leaving it alone.

13:38 Borkdude: Squeese: yes

13:38 Squeese: Borkdude: hmm, thanks :)

13:38 Borkdude: ,(+ 1 2 3)

13:38 clojurebot: 6

13:38 Borkdude: ,[a b c]

13:38 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(NO_SOURCE_PATH:0)>

13:39 Borkdude: ,'[a b c]

13:39 clojurebot: [a b c]

13:39 Borkdude: ,['a 'b 'c]

13:39 clojurebot: [a b c]

13:39 Borkdude: see? ;-)

13:39 Squeese: yeah :)

13:40 robermann_: zilti: it should be a trivial exerices to use overtone to play the sounds; overtone is written in clojure (http://overtone.github.com/)

13:42 Squeese: ha wow, '[a b '(c d)) gives me: [a b (quote (a b))] did I get a vector with symbos a, b and a list with symbos quote etc?

13:42 symbols*

13:42 Borkdude: ,(quote ')

13:42 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: Unmatched delimiter: )>

13:43 Borkdude: eh

13:43 Squeese: , '[a [

13:43 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

13:43 Squeese: ops

13:43 , '[a '(b)]

13:43 clojurebot: [a (quote (b))]

13:43 Borkdude: ' is a reader-macro for quote

13:43 I think

13:44 (quote [1 2 3]) => [1 2 3]

13:44 Squeese: funny :)

13:44 daniel__: what function do i need here? (map #(???) ("line" "line" "line")) = ("1 line" "2 line" 3 line")

13:44 Borkdude: (quote '[1 2 3]) becomes (quote (quote [1 2 3])) => (quote [1 2 3])

13:44 daniel__ take a look at map-indexed

13:45 daniel__: thanks Borkdude

13:46 Borkdude: ,(map-indexed (fn [idx itm] (str idx " " itm)) ("line" "line"))

13:46 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn>

13:46 Borkdude: fuck, I should try those out first ;)

13:46 Squeese: Im happy I choose to look into Clojure when deciding between lisp's, not really happening in #scala :P

13:46 alandipert: ,(map (partial apply str) (range) (repeat \space) '("list" "list" "list"))

13:46 clojurebot: ("0 list" "1 list" "2 list")

13:46 Squeese: +anything

13:47 alandipert: map-indexed would be better if it weren't for the space you need to add

13:48 Borkdude: ,(map-indexed (fn [idx itm] (str idx " " itm)) ["line" "line"])

13:48 clojurebot: ("0 line" "1 line")

13:48 Borkdude: more readble imho

13:49 daniel__: yep, thanks for the example

13:49 * alandipert is addicted to partial and comp, to the confusion of friends and coworkers

13:50 Borkdude: alandipert: I bet you are fond of Haskell? ;)

13:51 alandipert: kinda... i definitely lost the taste for naming intermediate variables somewhere on my quest

13:52 Borkdude: ccorn: what's up, I saw "What action to take on ccorn" in my Aquamacs

13:52 ccorn: didn't know what it was so I ignored it...

13:54 daniel__: ,(map-indexed (fn [idx itm] (str idx " " itm)) (repeatedly #(inc %) 1))

13:54 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.ClassCastException: sandbox$eval28$fn__31 cannot be cast to java.lang.Number>

13:55 daniel__: has to be a vector?

13:55 ,(map-indexed (fn [idx itm] (str idx " " itm)) (vec (repeatedly #(inc %) 1)))

13:55 clojurebot: #<ClassCastException java.lang.ClassCastException: sandbox$eval59$fn__62 cannot be cast to java.lang.Number>

13:55 daniel__: ,(map-indexed (fn [idx itm] (str idx " " itm)) (vector (repeatedly #(inc %) 1)))

13:55 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.ClassCastException: sandbox$eval90$fn__93 cannot be cast to java.lang.Number>

13:56 daniel__: ,(map-indexed (fn [idx itm] (str idx " " itm)) [1, 2, 3])

13:56 clojurebot: ("0 1" "1 2" "2 3")

13:58 Borkdude: daniel__: I think you meant (iterate inc 0)

13:58 dnolen: ibdknox: (- 1), yet another stupid bug in my compiler macro additions. that's fixed now.

13:58 Borkdude: but if you do that here, it will cause map to go over an infinite seq..

13:58 dnolen: if anyone knows how to run the CLJS tests I'm all ears.

13:58 ibdknox: dnolen: :)

13:58 no idea

13:59 Borkdude: daniel__: so you could do (take 10 (iterate inc 0)) or just (range 10)...

13:59 daniel__: Borkdude: yeah...and nvm, i got my code working :)

14:00 ibdknox: dnolen: there used to be a tests script I though

14:00 daniel__: (nth (map-indexed (fn [idx itm] (doto (str idx " " ((fitness-fn target) itm) " " itm) println)) (iterate #(evolve % (fitness-fn target)) source)) generations))

14:00 dnolen: ibdknox: it's there but it doesn't actually run the tests

14:00 it just builds the file, and I don't see how to run what it produces.

14:01 ibdknox: hm

14:01 yeah I dunno

14:02 you could compile the tests and run them in the browser?

14:03 dnolen: other option: add the test dir to your classpath for the repl and run the test_runner

14:05 uhoh

14:06 I'm not sure that telling people they shouldn't voice opinions is the way to go :/

14:06 zilti: http://vimeo.com/10896148 (Clojure - Stuart Halloway) seems to be a really awesome presentation for programmers coming from a non-lisp language

14:08 dnolen: ibdknox: I think the point is that some posts are just opinions - not technical discussion. I've done my fair share of opinion mongering :D

14:09 ibdknox: dnolen: Opinions are incredibly important in any community, whether it be technical or not

14:10 dnolen: ibdknox: to a point yes. but don't we have blogs for that?

14:12 ibdknox: dnolen: sure, but the mailing list is also a central meeting place for the community. Some opinions are not valuable, others should be discussed. There's no better place for the latter

14:12 dnolen: The cost of allowing the latter is that you'll get some of the former. That's how communities go.

14:13 dnolen: ibdknox: I don't think the post is necessarily about recent discussions. I think it's about a lot of threads that have astray in the past.

14:13 jli: I'm profiling some clojurescript. it seems like the reader is pretty slow, and 20% of the time is spent in cljs.core.truth. does this make sense?

14:14 ibdknox: dnolen: fair enough. I just know my knee jerk reaction to the email wasn't a good one. I suspect for newish people setting a tone like that will force them away :/

14:14 jli: how old is your clojurescript?

14:14 dnolen: jli: possible, I did some work on inlining truth, but in browsers like Chrome after advanced optimizations it didn't seem to be the bottleneck. Some more scientific benchmarking required tho.

14:15 jli: 20% truth_, 9.4% _equiv, 3.2% _count, 3.2% PushbackReader$read_char

14:15 ibdknox: jli: where are you running it?

14:15 jli: ibdknox: master as of last night

14:15 ibdknox: in Firefox 7

14:15 (is that what you mean?)

14:15 ibdknox: yep

14:16 dnolen: jli: can you try that in Chrome as well?

14:16 jli: it seems a lot faster in Chrome

14:16 ibdknox: jli: also, can you put a gist up of what you're running?

14:16 jli: dnolen: what can I use for profiling in Chrome?

14:16 dnolen: jli: the Web Inspector

14:16 ibdknox: jli: it has dev tools in it

14:17 dnolen: jli: the problem w/ inlining truth via the CLJS compiler is that it's not a code size win. You really want something like V8 Crankshaft to do that work for you.

14:23 jli: yeah, chrome is a lot faster. 2.5% _equiv, 2.3% call, 1.3% truth_

14:23 dnolen: you mean Chrome's JS engine is doing the inlining?

14:23 dnolen: jli: yes

14:24 jli: huh, I wonder if that's the main difference?

14:24 ibdknox: probably

14:24 jli: truth_ is all over the place

14:24 327k calls

14:24 dnolen: jli: most likely. The JS engines really should do that work for us.

14:25 jli: truth_ is good. It removes all the crazy semantics around JS truthiness / falsiness

14:25 ibdknox: dnolen: I sincerely hope we don't change the property syntax

14:25 jli: yeah

14:25 I'm going to manually inline truth_ in my compiled cljs and see if it's faster in firefox

14:26 dnolen: ibdknox: What's your concern after the discussion?

14:26 ibdknox: dnolen: it's conflating concepts that don't belong together. Interop should be interop. Map-like keyword access should be reserved for maps.

14:29 dnolen: ibdknox: I think rhickey's points about the issue are sound. It's not about interop so much as it's about being able disambiguate property / method calls. We don't have that luxury in JS.

14:29 ibdknox: my main concern was only around setting.

14:34 ibdknox: dnolen: his point is that early users were confused by it. Every single one of those early users was a Clojure programmer... They're the only ones that *would* be confused. A JS person already knows of this distinction

14:35 dnolen: ibdknox: it's also not map-like keyword access really. the dot operator is a special form and not composable.

14:35 ibdknox: that's not entirely true, (.foo x 1 2) will be a fn call. (.foo x) won't.

14:36 plenty to trip up people who don't know anything about Clojure.

14:36 ibdknox: I think that's an ambiguity that shouldn't exist, but I may be in the minority there

14:38 dnolen: ibdknox: if we don't got there, the above confusion will still exist. the change removes ambiguities around calling conventions.

14:40 ibdknox: also some JS apis will do multi-arity stuff via arguments. So in the current system you have to write (. x (foo)) (.foo x 1) (.foo x 1 2)

14:40 ibdknox: that's not trueh

14:40 dnolen: with the proposed change, (.foo x) (.foo x 1) (.foo x 1 2), I think that's a win.

14:40 ibdknox: -h

14:40 (. x (foo)) (. x (foo 1)) (. x (foo 1 2))

14:41 zilti: dnolen what about doto?

14:42 dnolen: ibdknox: the problem here is that . tries to uphold the Lisp convention. fn first. that's abandoning it.

14:43 ibdknox: dnolen: my argument isn't really a technical one, it's about fitting in. Keywords have 0 meaning in the languages that are interop'd with, symbols map logically with the things people are used to.

14:43 dnolen: I've always thought of it as the function being dot

14:43 dnolen: the thing I'm doing it to is x, and what I'm doing is applying some function to it. It's very much like the threading operators which make a lot of sense to me

14:43 srid: can I avoid the `range` in (reduce #(...) val (range (dec (count arg1))))?

14:44 ibdknox: dnolen: it's actually more internally consistent with Clojure I think

14:44 srid: elements of range arrya will be ignored in the reduce fn

14:44 here's the complete function, https://gist.github.com/1289963

14:45 dnolen: ibdknox: (. x (foo)) was always considered a degenerate form as far as Lisp conventions go in Clojure. If . is a function, then it's something like Obj-C msg_send, which just isn't true at all.

14:46 jli: heh: cljs.core.truth_("\ufdd0'else")

14:47 zilti: "(defn index-filter [pred coll] (when pred (for [[idx elt] (indexed coll) :when (pred elt)] idx)))" I don't understand that at all. How does that work?

14:48 dnolen: jli: https://github.com/clojure/clojurescript/tree/80-inline-truth, I have branch w/ truth inlining

14:49 Borkdude: ,(doc index-filter)

14:49 clojurebot: Cool story bro.

14:50 Borkdude: zilti, this isn't a std clojure function?

14:51 zilti: (when pred ...) just means: when a predicate is provide

14:51 d

14:51 zilti: thes rest is a standard for with :when guard

14:52 ibdknox: dnolen: like I said, I have no technical ground to stand on and since it's been firmly declared that's what I need, I'll just leave it be.

14:52 zilti: Borkdude: I don't understand that part that's going on in the for part. indexed is supposed to be a function returning pairs

14:53 Borkdude: zilti: I don't think indexed is in clojure.core, keep-indexed is

14:53 zilti: Borkdude: Yes, I know it isn't in the core. I have that code from a presentation slide

14:54 Borkdude: zilti: (keep-indexed pred coll) is what we would write nowadays I think

14:55 zilti: Borkdude: Instead of the whole thing inside the for block?

14:57 dnolen: ibdknox: I agree w/ you as far as aesthetics are concerned. But I just can't see what would be better for JS property access.

14:57 we lose a semantic wart and gain an aesthetic one

14:57 ibdknox: dnolen: just leave it be. This is a documentation issue, not something we should special case in the language. This is a result of the host platform

14:58 dnolen: ibdknox: but ClojureScript already removes so many problems that exist in the host.

14:58 Borkdude: zilti: for example (keep-indexed #(if (even? %2) %1) (range 100 110))

14:58 dnolen: ibdknox: proper scoping rules, fixes truthiness/falsiness, etc.

14:58 ibdknox: that's true, but should we really add syntax that only matters for JS?

14:58 dnolen: this is only for interop

14:59 Borkdude: zilti: it means: I'm only interested in the indexes for the numbers in the range that are even

14:59 ibdknox: dnolen: I agree, Clojure abstracts JS away... but you can't abstract the host from features designed to interact with it

14:59 Borkdude: zilti: so it is slightly different than I said at first

15:00 zilti: Borkdude: Apparently a long way to go for me. Where does the second argument in the anonymous function come from?

15:00 Borkdude: zilti: so: (defn index-filter [pred coll] (keep-indexed #(if (pred %2) %1) coll))

15:01 zilti: if you wish: (defn index-filter [pred coll] (keep-indexed (fn [idx elt] (if (pred elt) idx)) coll))

15:01 dnolen: ibdknox: rhickey seemed OK w/ moving forward without addressing it, but fundamental issues like this can end up really creating headaches down the line.

15:01 Borkdude: #(... %1 %2) is an anonymous function, %1 is the first argument, %2 the second, etc

15:01 dnolen: ibdknox: I think by now he has a good idea of what sort of things plague newcomers to a language :)

15:02 ibdknox: dnolen: Ok, so how about a convention that is property accessors are done by (aget x "foo") and make (.foo x) always mean call a method if this is really something that has to be done

15:02 dnolen: I'm not new to languages either :)

15:02 dnolen: and I would argue he generally doesn't care about newcomers, but maybe that's me being cynical based on all of his communications lately

15:03 zilti: Borkdude: I know, but where are the arguments from? Where's the idx arg from and where's the elt argument from?

15:03 dnolen: ibdknox: aget is prevents advanced optimization

15:03 ibdknox: dnolen: I meant less that exact mechanism, and instead something like it. Sorry, that was misleading

15:03 Borkdude: zilti: keep-indexed expects a function of two arguments, the index and the element

15:03 jli: dnolen: if code is testing truth on an expression, do you use a local variable or avoid inlining it?

15:03 Borkdude: zilti: it will index the collection and then apply the function to every index and element of the collection

15:04 dnolen: ibdknox: I don't think that's true at all, but I think he does expect the community to do that work.

15:04 jli: if truth test is an expression context, no inlining

15:04 ibdknox: ah a new special form

15:04 Borkdude: zilti: so a bit like indexed, only less explicity

15:04 -y

15:05 dnolen: ibdknox: (js-get x foo) ?

15:06 ibdknox: dnolen: given that it's only specific to JS... I guess. Though we could make it something more general as to mean "interop property accessor"

15:06 that way it's at least sensical in other contexts, even if it's unlikely to be used

15:06 hell

15:07 we could extend get to do it

15:07 zilti: Borkdude: Ah it needs a function taking two args. Now I see. Thanks! But, getting back to "(defn index-filter [pred coll] (when pred (for [[idx elt] (indexed coll) :when (pred elt)] idx)))" again, how does that destruction work?

15:07 Borkdude: zilti: keep-indexed is more general than indexed, but you can do the same with it:

15:07 ibdknox: (get x foo)

15:07 Borkdude: ,(keep-indexed #(vector %1 %2) ["foo" "bar"])

15:07 clojurebot: ([0 "foo"] [1 "bar"])

15:07 ibdknox: I guess it'd be (get x 'foo)

15:08 dnolen: ibdknox: yeah can't overload get like that, 'foo might be a real key in a ObjMap

15:08 ibdknox: dnolen: yeah

15:08 Borkdude: zilti: ah, for has the same destructuring (I think) as let, defn etc

15:09 zilti: Borkdude: It's less about what the code does now, it's more about what is the exact syntax for that destruction thingy - is there an info document somewhere or can you describe that in a few words?

15:09 dnolen: (-get x foo)

15:09 Borkdude: so: (let [[a b] [1 2]] a) => 1

15:10 zilti: just google on clojure destructuring

15:10 ibdknox: dnolen: Maybe we do need to solve this problem, but I don't think the weird syntax proposed is that solution. If we're just doing it for JS, we should do something that makes more sense. Maybe it is (-get ..) or something similar, maybe it's something else entirely.

15:10 dnolen: either way, adding a specific syntax to a space that's already confusing isn't the right thing to do

15:10 dnolen: ibdknox: -get would interesting, - already connotates a low level op. it also mans dot operator is always fn call

15:10 Borkdude: ,(for [[a b] [[1 2] [3 4]]] a)

15:10 clojurebot: (1 3)

15:10 jli: Borkdude: zilti: I always look at the docs for let http://clojure.org/special_forms#Special%20Forms--(let%20[bindings*%20]%20exprs*)

15:11 dnolen: s/man/means

15:11 lazybot: <dnolen> ibdknox: -get would interesting, - already connotates a low level op. it also meanss dot operator is always fn call

15:11 zilti: Borkdude: Oh. indeed. I searched for "clojure destruction" which didn't give me anything useful

15:11 ibdknox: dnolen: that's the kind of consistency we should go for I think

15:12 Borkdude: zilti: the simple case of for is (for [a [some-seq]] ....), in every iteration a becomes the next element from some-seq

15:12 zilti: with destructuring you just destructure on the next element from some-seq

15:13 dnolen: ibdknox: I like the idea of -get, posted on the ML.

15:13 zilti: Borkdude: Thanks a lot. I'll take a look at that. But for today I'm kinda tired and have already learned a lot...

15:14 Raynes: http://stackoverflow.com/questions/3337888/clojure-named-arguments

15:14 * Raynes finds a horn and toots it.

15:14 jli: blah, so truth inlining reduced the # of calls pretty dramatically, but I couldn't get rid of it everywhere. dnolen: crankshaft is probably able to inline functions even applied to expressions, right?

15:15 dnolen: jli: I would think so.

15:15 Borkdude: zilti: ok, have fun and be careful, because Clojure is addictive

15:15 dnolen: jli: yeah it's impossible to inline truth everywhere because of expression contexts.

15:15 jli: yeah, okay. I guess I'll quit trying to read-string 500 records at a time

15:16 dnolen: if(var x = foo(); ..) { … } sadly not allowed in JS.

15:16 jli: boo

15:17 dnolen: jli: out of curiosity how long is that taking?

15:24 jampart: newbie Q: is there really no way to extend a "class" (datatype) in Clojure?

15:25 dnolen: ibdknox: I'm liking this -get compiler idea macro more and more. We can validation and ensure that x in (-get foo x) must be a symbol.

15:26 jampart: there's no subclassing in Clojure if that's what you mean.

15:26 ibdknox: dnolen: yeah, it allows for a much greater degree of flexibility and is internally consistent :)

15:27 dnolen: ibdknox: hopefully people bite, fingers crossed.

15:27 jli: dnolen: to read 490 records (~98k of text) and render relatively straight-forward HTML from it is ~5.5s in Firefox 7 and ~1.8s in Chrome.

15:27 ibdknox: jli: with the inlining?

15:28 jli: you're dealing with seq performance there I bet...

15:28 dnolen: jli: yeah curious about how long that takes w/ inlining, this is a good benchmark.

15:29 ibdknox: dnolen: are you interested in sitting down with folks and talking about the pods stuff at the Conj?

15:29 dnolen: ibdknox: haha, I hardly know anything about Pods, nor how that concept could be leverage efficiently in ClojureScript :)

15:30 jampart: dnolen: so protocols are the only means of subtyping? Can't even subtype records?

15:30 jli: ibdknox: dnolen: that was without. with my manual inlining, it's maybe ~4.7 in firefox and ~1.2 in chrome. dnolen: I'll try your branch later and also try to get more accurate timing

15:30 ibdknox: dnolen: haha I don't either. So I guess maybe the correct thing to say is, would you be interested in working on an efficient seq-like thing

15:30 dnolen: jampart: no subtyping.

15:31 jampart: protocols aren't really subtyping.

15:31 jampart: dnolen: so even protocols can't be "derived", as in Haskell's type conditions?

15:32 dnolen: jampart: don't know Haskell that well, but yes from what I understand Haskell support derivation - Clojure does not.

15:33 ibdknox: definitely interested in the discussion. we should corner rhickey and get him to give us some pointers.

15:58 btby: I'm new to Clojure. I'm currently going through Peter Norvig's AI book and was wondering if there was an easy way to leverage the Java code for the book (https://code.google.com/p/aima-java/)? I'd like to use Clojure as my exercise language, considering that the original book had Common Lisp as implementation language.

16:02 Borkdude: btby, there is a Peter Norvig AI/Lisp book

16:03 btby: highly recommendable: http://norvig.com/paip.html

16:04 At the time, I found it the best programming book I ever read (halfway through my CS studies)

16:05 btby: Borkdude: Thanks! I've heard about it, but assumed AI: Modern Approach to be a proper superset. Now I'll look closer.

16:05 Borkdude: btby: those are two different books

16:05 btby: the one I mentioned is more about Lisp and shows the power of the language using AI examples

16:06 btby: the other one is more about AI and the code is just there to illustrate how things works in AI

16:06 btby: at least, that is how I understood it while reading both ;)

16:06 btby: Borkdude: I'm using AIMA (the non-Lisp one) for the course I'm taking at the moment.

16:08 Borkdude: btby: I don't really get the question. The lisp code is up here: http://aima.cs.berkeley.edu/lisp/doc/overview.html

16:08 btby: apparently the Java code is also available. Would you like to use it from Clojure?

16:08 btby: or translate it to Clojure

16:09 btby: Borkdude: Yup, using Java from Clojure if it's possible, although if the modification of Common Lisp code is not hard, I'd assume that to be more educational.

16:09 Borkdude: btby: it would definitely a cool project to make a Clojure port ;-)

16:09 br

16:09 be

16:10 btby: Challenge accepted, then. =)

16:11 But in case I need Java to do that last-minute assignment, is it still possible?

16:11 Borkdude: btby: you can do Java interop in Clojure, yes?

16:12 btby: http://clojure.org/java_interop

16:13 gfredericks: so what happens if you try to use clojure 1.3 and one of the deps asks for 1.2?

16:14 btby: Borkdude: Thanks!

16:23 amalloy: gfredericks: in conflicting dependencies, the one specified in the top/main level wins

16:23 gfredericks: huh. I never would have guessed that.

17:15 duck1123: do you need to type hint this when doing gen-class methods, or does it already know the type of that one?

17:34 arohner: duck1123: clojure will infer the types if you're overriding methods. For new methods that don't override anything, you'll need hints

17:35 amalloy: arohner: he was asking about hinting the `this` parameter. i'd be surprised if whether you override a method influences clojure's ability to infer that

17:35 arohner: oh, right. reading comprehension FTW

17:47 droidboi: hi

17:50 i am nu 2 this

17:55 droidxmx: what does an N at the end of an int mean?

17:57 gregh: a following M means BigDecimal, but I'm not sure what N means

17:58 see http://clojure.org/reader for details

17:59 droidxmx: gregh: ok thx

17:59 ibdknox: ,(type 1N)

17:59 clojurebot: clojure.lang.BigInt

18:00 ibdknox: droidxmx: ^

18:00 droidxmx: cool

18:02 'nox: nice one

18:02 gregh: ,(type 1M)

18:02 clojurebot: java.math.BigDecimal

18:03 gregh: so does /reader need to be updated to add N?

18:08 droidxmx: ,1

18:08 clojurebot: 1

18:08 todun: I was using emacs to work and the swank server connection closed. This is confusing me because I thought it is a server running on my local machine. Is this normal?

18:09 droidxmx: nice

18:09 Apage43: todun: if the jvm it was running in died or crashed for some reason

18:10 todun: Apage43: I see. what if there is no warning?

18:10 Apage43: the jvm doesn't give any warning. can it still just randomly crash?

18:10 ivan`: is there an Anki or Mnemosyne deck with Clojure flashcards anywhere?

18:14 Apage43: todun: *shrug* depends what caused it to blow up

18:14 todun: so I shouldn't worry about it I guess..

18:14 thanks.

18:15 Apage43: probably not. If it keeps happening you might want to care more.

18:17 todun: Apage43: ok.

18:25 kanja: I'm having a ton of trouble getting slime installed with clj - I keep getting errors like: "Symbol's function definition is void: 

18:25 define-slime-contrib" when trying to enter slime mode. I found the offending line in swank-clj's definition, but I don't know where slime-contrib should be. Any ideas?

18:26 amalloy: don't use swank-clj. it's like a hundred years old

18:26 er

18:26 no, that's ritz's new name, isn't it? i'm not sure now

18:27 kanja: it's in the package.el repository, and most of the install walkthroughs I see use it...

18:29 amalloy: kanja: from https://github.com/pallet/ritz it looks like swank-clj was renamed to ritz, not the other way round. but anyway, i was thinking of slime-clj, which definitely is old :P

18:30 kanja: amalloy: ah - yeah I'm tyring to get slime-clj installed. If that's old, what should I use instead?

18:31 amalloy: kanja: have you looked at that github link? he seems to bundle slime-ritz with the swank package

18:33 i never got ritz working, myself; i still use the older swank-clojure with one of technomancy's snapshots of slime

18:33 kanja: I'm kind of a newb with slime/swank actually - I'm not really sure how to use it

18:37 todun: I am writing the following routine to remove duplicates. I think the problem is with the second condition to cond, but whenever I try to give it an independent expression, the emacs indentation complains that it's wrong: http://pastebin.com/kWDvPDQ8

18:37 any help is appreciated. thanks.

18:40 amalloy: todun: you seem to have included (rest lst) inside of the (and) test instead of after it

18:40 todun: amalloy: yes. I realize that. but emacs complained about my indentation when I did otherwise. and I get an exception when I run it.

18:41 run it with both the (rest lst) in and out of the and block(is that what it's called?).

18:41 amalloy: emacs is not complaining about your intentation; cond just doesn't indent in a very readable manner

18:41 your exception is due to there being other issues

18:41 todun: amalloy: that figures :P

18:42 amalloy: for example, (rd (lst)) should probably be (rd lst)

18:43 todun: amalloy: oh. I can leave the list out of parens?

18:43 I see. ok.

18:43 amalloy: it's nothing to do with "can you leave it out". parens always (except when they don't, as discussed yesterday) mean "call the stuff inside as a function"

18:44 todun: amalloy: ok. sorry. I keep thinking of lists like an exception. thanks.

18:48 amalloy: thanks. it compiles now. testing it...

18:52 amalloy: now I get a stackoverflow. I know if you do recursion in clojure for large values without using compiler optimizations you get SO. But for small values what could be causing my SO? http://pastebin.com/ynVTZiwt

18:52 amalloy: :else (rd lst) - your else clause just starts the same job over again without simplifying it

18:54 todun: amalloy: I thought doing that in cond's and clause took care of it in the call back to the function, or no?

18:54 Apage43: also you can recur there, no?

18:54 todun: Apage43: ok I will try that.

18:54 Apage43: todun: you haven't modified lst..

18:55 todun: Apage43: I'm wary of that because I try it for another function I write and I get my REPL hanging...

18:55 Apage43: modified lst?

18:55 Apage43: (rd lst)

18:55 will call rd with exactly what it was originally called with

18:56 so naturally if you hit that branch it'll be an infinite loop

18:56 todun: Apage43: will call recur in place of else solve that problem, no?

18:56 Apage43: .. no.

18:56 todun: uhm ok.

18:57 Apage43: What are you intending to pass to the function when you call it again?

18:58 todun: a list

18:58 Apage43: containing...

18:59 todun: for example

18:59 given (1 2 3 1 4 1 2), returns a sequence containing the elements (1 2 3 4),

18:59 in some order.

19:00 Apage43: well yes that's what you want rd to do

19:00 but specifically i'm talking about the part where you're recurring

19:00 what do you want to pass to rd in the next step

19:01 todun: Apage43: oh ok.

19:02 Apage43: I want to give it the list

19:02 that is reduced

19:02 from the previous steps.

19:05 archaic: is there a way to directly destructure a map in the binding: into ks and vals? ie (defn [m] (let [ks (keys m) v (vals m)] ...)

19:05 Apage43: sorry, can't wrap my head around what you're trying to do =/

19:05 gfredericks: archaic: well what you have there would certainly work if that's what you want. But there's a whole syntax for destructuring maps too

19:05 e.g., assigning specific keys to specific names

19:06 archaic: yea thats what i mean

19:06 gfredericks: and a few other features

19:06 but what you did there is not translatable into map destructuring

19:06 so I'm not sure what specifically you want

19:06 todun: Apage43: was that directed at me?

19:06 Apage43: ,(let [map {:a 1 :b 2}] (let [{a :a b :b} map] [a b]))

19:06 clojurebot: [1 2]

19:07 gfredericks: archaic: that ^ there is certainly an example

19:07 archaic: and this here I just googled seems to go over it in detail: http://blog.jayfields.com/2010/07/clojure-destructuring.html

19:08 archaic: I wanted something like (defn [[ks val] m]) where ks and vals are the keys and vals in m, rather than what I first wrote, since I seem to be using that alot

19:09 gfredericks: ,(let [m {:a 1 :b 2 :c 44}, [ks vs] ((juxt keys vals) m)] [vs ks])

19:09 clojurebot: [(1 44 2) (:a :c :b)]

19:09 archaic: yah that works, would that be reasonable macro?

19:09 gfredericks: archaic: aside from that kind of ugly mess, there's not direct support. I'm curious why you end up doing it a lot though.

19:11 also I don't know what you meant by "would that be a reasonable macro?"

19:11 since what I did was not a macro

19:12 archaic: I know, I meant wrapping what you did to get rid of the 'uglyness

19:13 gfredericks: rather than a macro I would just def (juxt keys vals) somewhere and use that

19:13 (def kvs (juxt keys vals)) and then (let [[ks vs] (kvs m)] ...)

19:13 archaic: yeah that works, thanks

19:14 gfredericks: sure

19:16 archaic: i still haven't found need to write a macro ever yet though :\ in about 3 months of clojure

19:16 gfredericks: that's a good sign.

19:18 archaic: except if your trying to learn them

19:19 gfredericks: why would you be trying to learn them if you don't need them? :)

19:23 todun: is it possible to pass the name given to a function in a let binding to the argument of a recursion?

19:23 gfredericks: o_o

19:23 amalloy: todun: first of all, you know distinct already exists, right? you're implementing remove-duplicates for practice?

19:24 todun: amalloy: yes.

19:24 to practice my recursion

19:24 amalloy: okay. well i think your algorithm is impossible, so working on your syntax is not going to help

19:24 todun: amalloy: oh. sigh.

19:25 I'll appreciate any suggestions. thanks.

19:25 amalloy: in order to remove duplicates of some sub-list x, you need to know what elements have already been "selected" to return in the previous iterations

19:25 todun: amalloy: so. using let can help, no?

19:25 as in binding that output to the next call.

19:26 *recursive.

19:28 gfredericks: todun: is your code posted somewhere?

19:28 todun: gfredericks: yes. let me repost it...

19:28 amalloy: todun: here's a quick sketch i put together trying to stick to simple language features: https://gist.github.com/1290310

19:29 archaic: todun, I would do something like (reduce some-fn #{} coll) where some-fn uses contains? to check for duplicate

19:29 todun: gfredericks: http://pastebin.com/ynVTZiwt

19:30 amalloy: the key point is that you have to manually track what elements have already been returned - given just the "current" sub-list you can't tell which elements of it to return

19:30 todun: amalloy: archaic seeing allot of new notation here. will take me a second to comprehend it all.

19:31 amalloy: ok. so using a compare between adjacent elements is not a good idea?

19:31 amalloy: todun: then how would you fix '(1 2 1) into just '(1 2)?

19:32 todun: that's why I was simultaneously checking if the list was distinct.

19:34 Apage43: todun: checking if distinct is distinct?, btw. distinct removes duplicates.

19:34 todun: Apage43: yes. it is sort of backwards. I was hoping to learn the different forms of recursion in clojure.

19:35 amalloy: todun: you're implementing distinct yourself. if you use it as part of your solution, you might as well just make it your whole solution

19:35 (def rd distinct)

19:36 gfredericks: brilliant!

19:36 todun: amalloy: true :)

19:36 * gfredericks goes and fixes up his code

19:36 Apage43: you can always look at how distinct is implemented. Mind it is lazy: https://github.com/clojure/clojure/blob/f5f827ac9fbb87e770d25007472504403ed3d7a6/src/clj/clojure/core.clj#L4413

19:37 gfredericks: huh. I didn't know it was lazy. ##(take 5 (distinct (range)))

19:37 lazybot: ⇒ (0 1 2 3 4)

19:37 gfredericks: well I'll be.

19:37 todun: Apage43: thanks.

19:38 amalloy: I'm still looking at your code and you use recur. I have code I wrote that uses recur. It compiles fine but it runs like for ever on small input. I think I'm missing the point of all these recursion optimizations. Can I post it?

19:39 amalloy: you can post anything you want :P. in this case i was using recur mostly because i wanted a loop, not because i wanted to "optimize" it

19:39 todun: amalloy: ok. thanks. http://pastebin.com/5txqZnU8

19:40 amalloy: that is so counter-intuitive that I'm not sure I understand. how can you use(surely you did and it works) recur to make a loop?

19:40 amalloy: or is this idiomatic clojure?

19:40 gfredericks: ironically, this recursive reversal seems like a great non-use-case for loop/recur

19:41 i.e., the simplest way is to use traditional recursion

19:41 (defn rreverse [coll] (reverse (map rreverse coll)))

19:42 except I forgot the base case

19:42 well it works for infinitely nested lists anyways :)

19:43 todun: the problem with using recur for rreverse is that recur only lets you make one recursive call. If you want to rreverse every element in the input list, you'd want to recurse for each element.

19:44 which you can't do with recur

19:44 todun: gfredericks: I see.

19:44 gfredericks: will a lazy seq do something similar?

19:45 gfredericks: recur has a lot more in common with imperative languages' loops than with the things that you would normally do recursively in an imperative language

19:45 Apage43: recur is not a function call. it means "rebind these vars and jump to the recursion point (beginning of the fn, or loop, usually)"

19:45 todun: gfredericks: since lazy seqs should only do work when they have.

19:45 gfredericks: todun: I think that's kind of a separate issue.

19:45 todun: Apage43: ok.

19:45 gfredericks: oh?

19:46 gfredericks: todun: mostly because I don't see how it relates :)

19:46 todun: your whole goal at the moment is to learn recur, is that correct?

19:46 todun: gfredericks: yes. or recursion in general.

19:47 gfredericks: what other languages are you familiar with?

19:47 archaic: ohhh I didn't know you could do nested destructuring nice.. refactor time (defn binding-test [{[x & xs] :content}] [x xs]

19:47 todun: gfredericks: though I'm brand new to programming, I've dabbled in quite a few.

19:47 java, scala, python.

19:48 I'm not particularly good in any of them. but I'm still learning. so if I say something that doesn't make sense..well, you know why.

19:48 gfredericks: huh. I hadn't prepared a general recursion lecture.

19:49 I assume you came across the term "tail call" recently?

19:50 todun: yes. sort of.

19:50 gfredericks: especially in my clojure readings.

19:50 TCO.

19:51 gfredericks: yeah

19:51 amalloy: when i was learning lisp, i had this idea that it was all about writing recursive functions, especially tail-recursive

19:51 todun: amalloy: oh.

19:51 amalloy: and in some ways, it is, but mostly you can let the standard-library functions do all the recursion for you, and write your code in terms of map, reduce, and so forth

19:52 todun: amalloy: ok. relying on higher-order functions to do the work.

19:52 amalloy: right. like gfredericks's definition of deep-reverse in terms of map instead of manual recursion

19:52 todun: amalloy: sadly, that doesn't help my agenda of learning recursion.

19:53 gfredericks: todun: do you have any actual problems/projects you're working on, or are you simply trying to learn clojure?

19:54 amalloy: &(letfn [(rreverse [coll] (if (sequential? coll) (reverse (map rreverse coll)) coll))] (rreverse [1 2 [3 4 5 {6 7} [8 9]]]))

19:54 lazybot: ⇒ (((9 8) {6 7} 5 4 3) 2 1)

19:54 todun: amalloy: I think clojure can be instructive in this way, because it has so many idiomatic ways of doing recursion. I just have to

19:54 amalloy: both actually.

19:55 gfredericks: todun: I think the "so many ways" that you're thinking of is really just an unfortunate side-effect of the JVM rather than an intentional language feature

19:55 todun: amalloy: one is one for school hw. another is for learning programming.

19:56 gfredericks: ok.

19:56 gfredericks: ideally there's just one way to do recursion, and TCO happens whenever possible

19:57 todun: gfredericks: ok. how so?

19:57 gfredericks: a function calls itself

19:57 that's how it works in haskell and erlang.

19:57 todun: gfredericks: uhm. ok. that makes sense.

19:57 gfredericks: I think (loop) is just syntactic sugar, as you could do the same thing with (fn ...)

19:58 amalloy: yes

19:58 todun: gfredericks: not too familiar with the mechanics in those languages but I've seen they do allow TCO(at least erlang)

19:58 gfredericks: amalloy: do you know why loop is listed as a special form?

19:58 todun: gfredericks: actually I was just reading up on loop now.

19:59 amalloy: gfredericks: technically only loop* is a special form

19:59 Apage43: todun: exactly. because they have TCO, the optimization happens automatically

19:59 todun: gfredericks: it seems like a way to do any kind of recursion you want.

19:59 amalloy: but the docs are pretty vague about it

19:59 ibdknox: I think I'm missing the point of Clojure-Dev list :/

19:59 Apage43: todun: clojure does not have TCO, which is why it has recur

19:59 gfredericks: amalloy: I just read today that "several special forms are actually implemented as macros" and it was weird. Made me think I don't know what "special form" means, because I thought it was mutually exclusive with macros.

19:59 amalloy: gfredericks: loop *could* be implemented as a macro on top of fn, but for performance reasons it is not

20:00 todun: Apage43: ok. I know scala has TCO and it relies on the JVM too.

20:00 Apage43: why is clojure different?

20:00 gfredericks: amalloy: okay, that makes sense of it

20:00 amalloy: assuming that the quote I just mentioned was mildly incorrect and the starred versions are the actual special forms

20:00 amalloy: gfredericks: you're right, special forms and macros are distinct and non-overlapping. but if you pretend that loop* doesn't exist, then loop is kinda like a special form

20:01 gfredericks: amalloy: so you think the docs page claims that let/fn/loop are special forms just for simplicity?

20:01 amalloy: yes

20:01 Apage43: todun: Scala can do what clojure's recur does, but it can't do TCO when the tail-call is not to the same function

20:01 gfredericks: kay. my world is right again.

20:02 Apage43: but clojure can't do it even when it is to the same function. I assume that's because it's dynamic.

20:03 Apage43: right

20:03 amalloy: gfredericks: clojure could do that but chooses not to. dynamism doesn't enter the picture

20:03 Apage43: clojure could just detect where you could use recur and replace it with recur

20:03 todun: Apage43: I thought scala couldn't do mutual recursion but could tco?

20:03 Apage43: but if we force you to use recur you can more easily understand when you are and aren't going to be consuming stack

20:04 gfredericks: amalloy: what's the rationale then?

20:04 amalloy: gfredericks: <Apage43> but if we force you to use recur you can more easily understand when you are and aren't going to be consuming stack

20:05 Apage43: you absolutely -know-, in clojure, that if you aren't using recur you are adding a stack frame

20:05 gfredericks: amalloy: so clojure just hates implicit TCO regardless of the jvm?

20:05 ibdknox: eh

20:05 todun: Apage43: so recur is like tco then, like the book says, no?

20:06 ibdknox: as hiredman said it the other day, if the JVM had TCO, Clojure would have TCO too

20:06 amalloy: i don't think so. if tco to other functions were possible, clojure probably wouldn't demand a special annotation saying "please do it"

20:07 gfredericks: okay, so it prefers all or nothing

20:07 rather than "just to self"

20:07 ibdknox: gfredericks: consistency is king

20:07 without consistency, it's impossible to be "simple"

20:08 gfredericks: I'm still confused about why dynamism has nothing to do with it.

20:08 would it not be a problem if a function altered the var it pointed to and then invoked that var "recursively"?

20:09 Apage43: recur is nice compared to automatic self-call optimization because you can't THINK it's going to work, have it compile and run, and then perform really badly because it couldn't do the optimization

20:09 if recur won't work, it won't compile

20:09 ibdknox: Apage43: I'm with you, I think being explicit in this case is valuable

20:10 gfredericks: s/it pointed to/that pointed to it/

20:10 lazybot: <gfredericks> would it not be a problem if a function altered the var that pointed to it and then invoked that var "recursively"?

20:10 Apage43: gfredericks: that's not self-recursion anymore, and not even scala can do that

20:11 gfredericks: Apage43: I'm not arguing it is I'm arguing the compiler couldn't tell that's not happening

20:11 so how is it possible to implement self-recursion in clojure?

20:12 I'm specifically responding to amalloy's "clojure could do that but chooses not to. dynamism doesn't enter the picture

20:12 "

20:15 amalloy: gfredericks: i think it's pretty hard to write code that does that even without implicit tco

20:15 gfredericks: you mean unintentionally?

20:15 amalloy: even on purpose you have to try pretty hard

20:16 gfredericks: (defn foo [& args] (foo (alter-var-root! foo ...)))?

20:16 amalloy: no good

20:16 gfredericks: how come?

20:16 amalloy: &(macroexpand '(defn foo [& args] (foo (alter-var-root! foo inc))))

20:16 lazybot: ⇒ (def foo (.withMeta (clojure.core/fn foo ([& args] (foo (alter-var-root! foo inc)))) (.meta (var foo))))

20:16 amalloy: the internal foo is not referring to the var at all,but to the local function name

20:17 gfredericks: okay, so then write it like the expanded version but without the function name

20:17 (def foo (fn [& args] (foo (alter-var-root! foo ...))))

20:18 amalloy: gfredericks: and now foo gets evaluated for the function call before the alter-var-root happens

20:18 Apage43: it could just choose not to do the optimization for unnamed functions

20:18 amalloy: i'm just saying, it might be possible to trick the compiler, but it's very hard to write code that does that and is otherwise correct

20:19 gfredericks: okay

20:19 amalloy: but anyway that's *not* a self-call anymore - it's a function calling to a named var

20:20 which happens to, for the moment, contain the same functino

20:21 gfredericks: I guess I didn't imagine an implicit-self-call-TCO implementation that distinguished, but I guess that'd be the way it would have to go, and it would still be useful based on what you just lernt me about the defn macro

20:21 * gfredericks still thinks vars are weird

20:22 Apage43: very good reason to leave them alone once you set them =P

20:23 amalloy: (binding [binding let] (...profit???))

20:23 gfredericks: lol

20:24 I figured out just in my own head that that wouldn't compile

20:24 * gfredericks is proud of hisself

20:26 amalloy: &(with-bindings {#'binding #'let} (binding [inc dec] (inc 1)))

20:26 lazybot: ⇒ 2

20:27 amalloy: that one compiles but doesn't actually do anything, which makes it more fun

20:30 * gfredericks just heard a country song in his head with the chorus "...cuz you can't change a macro at runtime"

20:31 droidxmx: hi

20:32 gfredericks: droidxmx: hi

20:32 droidxmx: hi gf

20:32 sup

20:33 gfredericks: vars

20:34 droidxmx: ?

20:34 vars?

20:34 clojurebot: http://www.slideshare.net/mudphone/fun-with-vars

20:34 gfredericks: (inc clojurebot)

20:34 lazybot: ⟹ 6

20:35 droidxmx: what is that?

20:37 gfredericks: what is what? vars?

20:38 droidxmx: yes

20:38 gfredericks: holy crap how did I go this long without knowing about with-out-str?

20:39 droidxmx: clojure.org/vars

20:40 droidxmx: I only mentioned it because it was the last thing that was talked about before you showed up

20:43 amalloy: hah, another excellent reason not to waste space by saying hi to everyone when you arrive. if you do, gfredericks will start talking nonsense at you

20:44 duck1123: So in 1.3, unchecked-divide is just / right?

20:49 amalloy: duck1123: that would surprise me. 1.3 doesn't default to ratios anymore?

20:50 duck1123: right... so where did unchecked divide go?

20:50 dnolen: ,*clojure-version*

20:50 clojurebot: {:interim true, :major 1, :minor 3, :incremental 0, :qualifier "master"}

20:50 dnolen: ,(/ 1 2)

20:50 clojurebot: 1/2

20:51 dnolen: ,unchecked-divide

20:51 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: unchecked-divide in this context, compiling:(NO_SOURCE_PATH:0)>

20:51 duck1123: I'm trying to compile aleph with 1.3 (ie. check all the things)

20:52 gfredericks: maybe it's what you get when you pass floats to /?

20:54 amalloy: ,(find-doc "unchecked")

20:54 clojurebot: -------------------------

20:54 clojure.core/*unchecked-math*

20:54 While bound to true, compilations of +, -, *, inc, dec and the

20:54 coercions will be done without overflow checks. Default: false.

20:54 -------------------------

20:54 clojure.core/unchecked-add

20:54 ([x y])

20:54 Returns the sum of x and y, both long.

20:54 Note - uses a primitive operator subject to overflow.

20:54 -------------------------

20:54 amalloy: uhoh

20:54 clojurebot: clojure.core/unchecked-add-in...

20:54 gfredericks: I guess that would imply it doesn't exist in the same sense though

20:54 dnolen: duck1123: unchecked-divide probably doesn't make much sense - long / integer will get you a ratio.

20:55 duck1123: if you coerce to double / float, you don't need unchecked.

20:55 amalloy: dnolen: perhaps just use quot?

20:55 duck1123: in the place I found it, it was dividing 2 longs. I presume the unchecked- was for speed

20:58 dnolen: duck1123: fwiw I had a similar problem in core.logic, you can abstract away the difference between 1.2.0 / 1.3.0 with a macro over the specific operation.

21:24 gfredericks: huh...the special forms page suggests that docstrings should be short: 1-3 lines

21:28 duck1123: gfredericks: that was before marginalia

21:29 gfredericks: wait is this awesome?

21:30 duck1123: marginalia would be more awesome if it extracted my doc strings correctly

21:30 gfredericks: why doesn't it?

21:30 duck1123: for the projects it works for, it looks awesome

21:31 there's some odd bug, there's a ticket in for it, but I haven't looked too deeply

21:31 it pulls out all my ;; comments, but none of my docstrings

21:32 gfredericks: huh.

22:54 kanja: I'm trying to get ritz swank working, and I'm getting "FileNotFoundException Could not locate swank/swank__init.class or swank/swank.clj on classpath" when I'm attempting to load slime - I'm assuming that I need to alter my classpath, but I don't know how - can someone point me to a resource on setting my classpath?

23:34 duck1123: kanja: do you have swank-clojure declared as a dependency?

23:36 amalloy: duck1123: that's frowned on these days anyway, right? supposed to install it as a plugin instead

23:37 duck1123: right, but he's using ritz, and if it's anything like the maven plugin, you need to declare it

23:37 using lein, sure, you should just install it as a plugin

23:38 kanja: duck1123: I think I don't? I attempted to install it via `lein plugin install ritz 0.1.7`

23:38 but that doesn't do anything with emacs, does it?

23:38 er nm, stupid quesiton

23:38 duck1123: using ritz, you still call mvn to do stuff, right?

23:39 kanja: I have no idea :(

23:39 duck1123: I would try declaring swank as a dependency

23:39 amalloy: i thought there was a lein-ritz

23:39 duck1123: is there? I thought it was just for maven

23:40 I'm thinking of Zi

23:40 amalloy: if anyone out there is developing stuff for clojure users that only works for maven, we should probably find out where they live and kill them

23:40 duck1123: well then, try installing the swank plugin as well

23:40 kanja: arg, why is getting slime setup so hard :(

23:41 try installing the swank plugin?

23:41 duck1123: lein install plugin swank-clojure 1.4.0-SNAPSHOT

23:41 kanja: thanks

23:42 that seemed to do something

23:42 duck1123: I think there's a more stable version, but that works well for me with 1.3

23:44 amalloy: I think a maven plugin is an acceptable exception for maven only

23:45 kanja: still not swank on my classpath...

23:46 amalloy: i don't even really know what a maven plugin is, so i can't argue this point

23:46 kanja: Why were people saying not to use swank-clojure? That was updated two days ago

23:47 duck1123: You're not supposed to declare swank as a dependency of your project

23:47 ibdknox: yeah, no more swank deps :p

23:47 duck1123: there have been a lot of changes to swank, and people were linking to old versions and it was causing problems

23:48 with lein's plugin system, there's no need

23:48 Of course, I say this knowing that I declare swank as a runtime dependency

23:48 But that's only because I launch a swank server as a side effect of starting my server

23:49 kanja: so m-x slime breaks, but closjure-jack-in works? Why the extra command?

23:49 duck1123: kanja: try lein-swank then M-x slime-connect

23:50 it's really pretty easy

23:50 I have a fn called slime-connect-to-server that connects to the default host port that I have bound to a key combo, it's effortless to connect

23:51 er: lein swank

23:53 kanja: Yeah, that works. Thanks!

23:53 Why does just m-x slime blow up then?

23:54 duck1123: M-x slime tries to start the server. Since it's designed for common lisp, it's a PITA

23:54 amalloy: kanja: that's trying to use CL slime

23:54 kanja: ahhhh

23:54 I see

23:54 makes sense

23:55 no wonder it's blowing up on the swank dependency then

23:55 duck1123: clojure-jack-in tries to eliminate the need to run lein swank

23:56 kanja: very cool

23:56 sorry I'm such a newb at this, I'm just starting to get setup with the clj ecosystem

23:57 duck1123: just to check, are you using an up to date emacs, using the starter kit? getting everything from elpa?

23:58 kanja: Yeah I'm using elpa, although that's pretty new to me. I've been stuck in a rut with my emacs conf for a long time

23:58 running emacs 23.3.1

Logging service provided by n01se.net