#clojure log - Jul 10 2011

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

0:01 scottj: mdeboard`: http://www.youtube.com/watch?v=lf_xI3fZdIg http://www.youtube.com/watch?v=kH0gOE7rj7g

0:02 + ritz + clojure-refactoring

0:09 sa125: Hi - how do I reverse a string? I tried (reverse "hello") and got (\\o \\l \\l \\e \\h).

0:09 [single backslash]

0:10 hiredman: ,(clojure.string/reverse "foo")

0:10 clojurebot: "oof"

0:11 sa125: hiredman - thanks!

0:13 hiredman: thats like 4

0:13 mdeboard`: Whoops.

0:34 ihodes: i'm (also) looking into covering Clojure & Java. what are the main pain points? should i be aiming it at Java programmers, or people without Java experience (though this will partially be based on what cemerick releases from The State of Clojure II)

1:00 pcavs: ,(doc source)

1:00 clojurebot: I don't understand.

1:01 amalloy: $mail mdeboard` to get the slime repl to recognize [] and {} as parens, try https://gist.github.com/1074292

1:01 sexpbot: Message saved.

1:03 amalloy: pcavs: source is in clojure.repl, which the bots don't load

1:03 pcavs: yeah, I keep reaching for clojure.contrib.repl-utils and keep remembering (eventually) that it's clojure.repl =\

1:07 $findfn 5 4 false

1:07 sexpbot: [clojure.core/== clojure.core/identical? clojure.core/isa? clojure.core/< clojure.core/= clojure.core/<= clojure.core/contains? clojure.core/bit-test]

1:07 pcavs: I guess I'm down to using (not (= ...)) then?

1:09 amalloy: pcavs: uh, are you looking for not=? if so, you probably meant

1:09 $findfn 5 4 true

1:09 sexpbot: [clojure.core/not= clojure.core/distinct? clojure.core/> clojure.core/>=]

1:10 pcavs: god dammit I'm stupid =\

1:13 talios: anyone know if theres an updated version of clojure.contrib.gen-html-docs thats 1.3 compatible?

1:13 zodiak: does anyone have a newb friendly clojureql and sqlite3 example ?

1:23 amalloy: talios: would marginalia be acceptable? it's probably 1.3-compatible, but i don't use it

1:23 Blackfoot: if I take a class as a function arg, how can I instantiate it?

1:25 talios: amalloy: I'm looking to roll a new clojure-maven-plugin and the IT tests fail on the gendoc goal under 1.3. I could switch it to the marginalia goal ( should test that works as well ). Tempted to just deprecate and remove both goals actually.

1:26 amalloy: Blackfoot: you have to use reflection

1:26 &(let [c Integer] (.newInstance c 5))

1:26 sexpbot: java.lang.IllegalArgumentException: No matching method found: newInstance for class java.lang.Class

1:26 amalloy: &(let [c Integer] (.newInstance c (into-array Object [5])))

1:26 sexpbot: java.lang.IllegalArgumentException: No matching method found: newInstance for class java.lang.Class

1:26 amalloy: feh. something like that

1:27 talios: its a static method so needs a different invovation

1:28 &(let [c Integer.class] (.newInstance c (into-array Object [5])))

1:28 sexpbot: java.lang.ClassNotFoundException: Integer.class

1:28 amalloy: talios: that's 100% wrong. Integer.class is java syntax

1:29 talios: yeh

1:29 Blackfoot: amalloy: ah yea, i see where you're going, thanks. i'll play around with the function calls

1:29 ah Class.newInstance can only invoke zero arg ctor

1:30 java.lang.Reflect may work

1:30 amalloy: &(.newInstance (.getDeclaredConstructor Integer (into-array Class [Integer/TYPE])) (into-array Object [5]))

1:30 sexpbot: java.lang.SecurityException: You tripped the alarm! package java.lang.reflect, Java Platform API Specification, version 1.6 is bad!

1:30 talios: Blackfoot: a class has a getConstrutors(Object, Object) method that'll return a Constructor instance you can us

1:30 amalloy: or there's clojure.lang.Reflector, which simplifies a lot of this stuff

1:30 ,(.newInstance (.getDeclaredConstructor Integer (into-array Class [Integer/TYPE])) (into-array Object [5]))

1:30 clojurebot: 5

1:30 talios: doh - declaredConstructor actually

1:42 replaca: talios: (looking back over history) No one has done anything to make gendoc work on 1.3 nor does there seem to be any plan to

1:42 talios: replaca: yeh, was just reading over the mailing list and came to the same conclusion

1:43 replaca: Basically, if there ain't a new-style contrib library, it ain't coming

1:43 although there is plenty of room to mmake a case for stuff

1:50 amalloy: talios: because new-contrib isn't one huge package with the clojure.org seal on it, if you want a 1.3 version of a contrib library, you can publish it yourself. i mean, you can't call it contrib without their permission, but you can easily make it available even if core isn't interested in it

2:02 talios: technomancy: around? Any chance of publishing swank-clojure 1.3.1 to maven-central? http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.github.technomancy%22 only shows 1.2.1

2:58 mdeboard`: Ok, I think I'm going to tear my hair out.

2:58 I've been trying to get SLIME repl working in emacs for hours now, I'm exhausted.

2:58 but I keep getting the same issue as here: https://github.com/technomancy/swank-clojure/issues/49

2:59 hiredman: my guess is you have the wrong slime

2:59 are you using clojure-jack-in ?

2:59 mdeboard`: yeah, clojure-jack-in, then I get a "Lisp lost connection" message as soon as I do anything at all.

2:59 Do I really have to get a 2-year-old release?

2:59 *branch

2:59 hiredman: what do you mean two year old release?

3:00 mdeboard`: Well, I grabbed the release from ELPA, thinking that would solve the problem

3:00 hiredman: no no

3:00 mdeboard`: Yeah this is really fucking confusing.

3:00 hiredman: follow the usage instructions https://github.com/technomancy/swank-clojure

3:01 mdeboard`: Right, but what slime do I use?

3:01 hiredman: it is pretty simple if you follow the instructions, if you don't it's your own fault

3:01 mdeboard`: No, no

3:01 That part is fine.

3:01 It connects to the REPL fine.

3:01 hiredman: you don't need a slime

3:01 mdeboard`: what.

3:01 replaca: mdeboard`: technomancy ha a blog post here that shows how

3:01 hiredman: clojure-jack-in actually loads a budled slime from the swank-clojure jar

3:01 replaca: http://technomancy.us/149

3:02 mdeboard`: Ok

3:02 That

3:02 hiredman: mdeboard`: you did the three things in the usage instructions for swank-clojure? and still get the error?

3:02 mdeboard`: hiredman: Yeah, but I was still requiring slime

3:02 and since I had slime installed

3:02 it was fucking everything up, maybe? I dunno, let me go fix up emacs config

3:02 replaca: mdeboard`: but make *absolutely* sure you don't have a swank in you project.clj or anywhere else in your classpath

3:03 mdeboard`: yeah, that's your problem

3:03 I had the same problem when I followed those instructions

3:06 talios: wow - google ran out of diskspace. Never saw that one coming - http://venturebeat.com/2011/07/09/google-on-massive-google-spam-influx-we-ran-out-of-disk-space/

3:08 mdeboard`: Alright, that did it.

3:08 That has been really frustrating.

3:10 hiredman: mdeboard`: for future reference #clojure is generally pg or pg13 language wise

3:10 mdeboard`: thanks, guy who pointed out that issue and hiredman

3:10 Did I cuss? Sorry.

3:10 I'm usually pg or pg13 language wise.

3:11 replaca: mdeboard`: :)

3:11 hiredman: :)

3:12 talios: ...so there we have it. slime is more of a hindrance to clojure newbies than hiredman. hiredman++

3:12 Blackfoot: is there a way to use alias namespaces in keywords? eg (:require really.long.ns :as lns) then use :lns/kw later?

3:13 hiredman: it's hard to say if technomancy's relentless pace of changes (aimed to make it easier) actually makes it harder or not

3:13 blog posts have a half life of a week or so it seems like

3:14 talios: right - going to go hunt some thai takeaway dinner whilst this clojure-maven-plugin release runs - back later.

3:14 scgilardi: Blackfoot: it looks like the alias is not effective there. seems to me that it should be.

3:15 hiredman: Blackfoot: ::some-alias/word

3:15 ,(require '[clojure.zip :as z])

3:15 clojurebot: nil

3:15 hiredman: ,::z/foo

3:15 clojurebot: :clojure.zip/foo

3:15 scgilardi: nice

3:15 zodiak: why does this http://pastie.org/2190990 in repl give me java.lang.Exception: Unable to resolve symbol: rs in this context (NO_SOURCE_FILE:17) ?

3:15 Blackfoot: hiredman: ooh nice, thanks

3:16 zodiak: well, I mean, I can guess why, I mean rather what's the solution and why :) :)

3:16 hiredman: zodiak: you have a lot of quoted symbols there

3:16 do you know what quoting does?

3:17 zodiak: hiredman: it's similar to a symbol in ruby/haskell .. no ?

3:17 hiredman: zodiak: if you don't know what quoting does then I suggest you a. stop doing it until you b. read up on it

3:18 zodiak: fine, but how do I solve that error in the meantime ? :)

3:18 hiredman: I just told you how

3:18 scgilardi: you also probably want (require '[clojure.contrib.sql :as sql]) at the top rather than ns and in-ns

3:18 (and do follow hiredman's advice)

3:19 zodiak: scgilardi: but if I do that, doesn't the whole namespace get potentially polluted by the methods/def's from contrib.sql ?

3:19 talios: mmm, that paste mentions an error on line 17, but only 10 lines pasted .. there no symbol rs even mentioned in the paste

3:19 hiredman: zodiak: I suggest reading docs on namespaces etc (and all the other docs, in order) linked to on the left sidebar of clojure.org

3:20 scgilardi: no. they would be pulled in if you used "use". require loads the namespace if not loaded. and the :as makes an alias that goes along with the code you posted (if fixed)

3:20 zodiak: hiredman: well, yes, I am trying to learn .. ergo.. why I am asking what's wrong

3:20 scgilardi: alrighty, that makes sense

3:20 hiredman: zodiak: you don't know what quoting does, and you are quoting stuff, so of course it doesn't do what you want

3:21 zodiak: *sighs gently*

3:25 talios: grr stupid irc client - shows that pastie.org content inline in the chat client, and only showed me 1/2 of it. Now I see all the quoting which makes hiredman's comments make sense to me.

3:25 but I was going for food... bbl

3:26 hiredman: talios: thats pretty slick

3:27 talios: hiredman: yeh, its good for image links, but for a moment I thought he'd actually pasted the content INTO the channel :) all I was was the mydb definition and I was sitting there thinking "quoted.... he's only quoting strings... whats hiredman on about?"

3:27 er, all I was seeing

3:28 amalloy: talios: "all i was was the mydb connection": someone who's meditating about how to write a function?

3:28 zodiak: oh. quote delays evaluation

3:28 hiredman: I should see about getting my growler thing to open pastebin links

3:28 amalloy: zodiak: no, it prevents it

3:28 zodiak: amalloy: fairy snuff :)

3:28 hiredman: functions delay evaluation (and delay binding) and so do delays

3:29 scgilardi: man I like functions

3:29 talios: amalloy: I am a database connection, nothing more, nothing less. a conduit to information for the rest of you :)

3:29 scgilardi: yeoman's work, t-man

3:30 hiredman: #9

3:30 ~#9

3:30 clojurebot: 9. It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures.

3:31 hiredman: ~#94

3:31 clojurebot: 94. Interfaces keep things tidy, but don't accelerate growth: Functions do.

3:33 ihodes: ~#42

3:33 clojurebot: 42. You can measure a programmer's perspective by noting his attitude on the continuing vitality of FORTRAN.

3:34 ihodes: *goes to cbots source*

3:34 * ihodes realizes that /me is what he should have used

3:34 amalloy: $google alan perlis quotes fortran

3:34 sexpbot: First out of 618 results is: Perlisisms - "Epigrams in Programming" by Alan J. Perlis

3:34 http://www.cs.yale.edu/quotes.html

3:34 amalloy: ihodes: ^

3:35 hiredman: very apropos, the code that grabs the epigrams uses a delay

3:35 ihodes: amalloy: excellent; i couldn't remember the name of the list

3:35 zodiak: day 2 of clojure, and I managed to get sqlite spitting out tuples onto a webpage. spiffy :)

3:35 thanks everyone.

3:35 amalloy: ihodes: i can't either. but remembering another alan's last name is easy enough

3:36 ihodes: ~#113

3:36 clojurebot: 113. The only constructive theory connecting neuroscience and psychology will arise from the study of software.

3:36 ihodes: = my life plan

4:12 amalloy: anyone know of a way to look at a java.lang.reflect.Method object and tell whether it's got varargs?

4:13 oh uhm. i'll try the isVarArgs method

4:13 talios: varargs under the covers is just an array.

4:13 amalloy: talios: i know

4:13 talios: or that :)

4:13 amalloy: but i'm writing a javadoc facility, and the anchor links are different

4:19 talios: ahh - generating javadoc from clojure or just in clojure?

4:19 amalloy: $javadoc Class

4:19 sexpbot: http://download.oracle.com/javase/6/docs/api/java/lang/Class

4:20 amalloy: talios: wrote this earlier tonight, and trying to get it to generate the right method anchors as well

4:20 talios: ah cool

4:21 * talios pushes clojure-maven-plugin 1.3.8 to maven central. mmm, also realised I've been out of clojure hacking for so long none of my hack projects are 1.3 compatible ;( I should rectify that :)

4:27 amalloy: $javadoc Class getMethod

4:27 sexpbot: http://download.oracle.com/javase/6/docs/api/java/lang/Class.html#getMethod(java.lang.String,%20java.lang.Class...)

4:27 amalloy: talios: look at this horrible anchor link you have to build

4:28 talios: oh lovely

4:30 amalloy: and that still doesn't handle everything: generic types, for example

4:37 hsaliak: talios: thanks for that :) i use the plugin

4:38 talios: hsaliak: cool. I'm thinking I need to trim it down. esp. given that gendoc isn't available in 1.3 I'm tempted to remove clojure:gendoc - going to look at killing clojure:test as well ( using the new surefire extensions mechanism ).

4:41 hsaliak: talios: not aware of the surefire extensions.. :-/

4:42 talios: hsaliak: its a recent addition, allows you a thirdparty test framework or something to introduce new "tests" to run as part of the standard test goal/test reports

4:42 ( and test counts )

4:42 hsaliak: talios: i mainly use it for getting clojure on android it integrates nicely with the android plugin, otherwise i use lein

4:42 i see

4:43 talios: neat. any problems with clojure on android? i assume you need everything AOT'd?

4:44 hsaliak: talios: yes everything AOTd :)

4:44 talios: well, the memory usage needs to be reigned in, sometimes i need to be careful on using list comprehensions as you would normally, but i think overall its OK. The annoying thing is to wrap all the java libraries

4:45 but its worth it

4:45 dynamic functional languages make it a little hard to optimize on memory i'd suspect

4:46 talios: mm, technically if everything is AOT'd, is it still dynamic..

4:46 hsaliak: have not tried introducing type hints and the like into whatver little code i have written

4:46 of course

4:46 hiredman: well, android is a new vm, they just turned on the jit for it, so it will be a while till matches hotspot

4:48 hsaliak: i think biggest issue is the load time for the app

4:48 a few seconds is bad

4:49 talios: I'd be happy with a few seconds. My android is sooooooo friggen slow now :( Old school HTC Magic running 2.2 cyanogen, no JIT, and seems to get more flaky everyday

4:51 brb

4:53 amalloy: $javadoc java.util.Collection add ;; you even have to say E here, despite that being mostly a figment of the compiler's imagination

4:53 sexpbot: http://download.oracle.com/javase/6/docs/api/java/util/Collection.html#add(E)

9:18 the-kenny: clojure.test/are needs destructuring for the argv-vector

9:19 to do something like (are [[x y] v] (= v (get (coord x y) ...)) ...)

9:35 jimi_hendrix: is there a good guide to setting up clojure with slime? everything i have found via google is out of date

11:06 Netfeed: what's the best way to print what's inside a map? something simillar to perls Data::Dumper

11:08 s/map/hash

11:08 sexpbot: <Netfeed> what's the best way to print what's inside a hash? something simillar to perls Data::Dumper

11:11 jimi_hendrix: where do you guys install lein?

11:11 mdeboard`: I did in /home/me/

11:12 Vinzent: script in /usr/local/bin

11:19 Scriptor: C:\lein :/

11:20 mdeboard`: god, why

11:20 WHY

11:21 @ Scriptor

11:21 I cannot even imagine

11:21 windows is for games and watching Netflix

11:21 Scriptor: mdeboard`: and when spilling coffee somehow only breaks your osx partition

11:22 mdeboard`: Ew

11:23 Scriptor: actually, it's not *too* bad, I've got emacs for windows, gvim, and mingw32 so it's ok enough

11:23 mdeboard`: Yeah it's just so much extra work getting a dev env set up

11:27 Does anyone here use paredit for emacs? It's been annoying for me but recommended everywhere.

11:28 sritchie: mdeboard`: yup, I'm a big dan

11:28 s/dan/fan

11:28 sexpbot: <sritchie> mdeboard`: yup, I'm a big fan

11:29 sritchie: M-( and M-s are my two favorites -- M-( wraps parens around the following s-expression, and M-s breaks the parens from around the current s-expression

11:29 mdeboard`: sritchie: Ok, I'll ask you then. I've got like {:foo {:bar baz}}. I want to instead do something like {:foo bar :baz x}

11:29 ah

11:29 * Vinzent can't imagine, how it could be possible to edit lisp code without paredit

11:29 sritchie: yeah, so, go into :bar :baz, somewhere along there, and type M-s

11:30 mdeboard`: Vinzent: I've got paren highlighting and the normal "mismatched parens" emacs warning

11:30 sritchie: mdeboard`: yeah, that'll happen if you use kill-word-backward, and accidentally jump over a paren

11:30 the solution is to use M-delete instead -- it ignores parens, just killing words

11:30 mdeboard`: Cool

11:31 M-s is what I needed :)

11:32 And then a more basic Clojure question. In {:foo bar}, if foo is a passed-in arg with a value, how do I make the output of the function display the value of foo, instead of literally "foo"

11:32 Vinzent: btw, I personally prefer paredit-splice-sexp-killing-backward over just splice-sexp (bound to C-M-i (I'm using M-i,j,k,l for cursor movements))

11:32 mdeboard`: I assume some token before foo

11:33 sritchie: Vinzent: it's bound to M-up too, I think

11:33 mdeboard`: that code you have there is a map data structure, mapping the keyword :foo to the value bar

11:33 mdeboard`: Oh, right

11:34 sritchie: keywords evaluate to themselves, like numbers

11:34 (defn apply-foo-to-bar [foo] (foo bar)) will do the trick

11:35 Vinzent: sritchie, but arrow keys are so slow! :)

11:35 sritchie: haha, good point

11:36 ,(let [foo +, bar 10] (foo 2 bar))

11:36 clojurebot: 12

11:36 sritchie: (let [foo +, bar 10] {:foo bar})

11:36 ,(let [foo +, bar 10] {:foo bar})

11:36 clojurebot: {:foo 10}

11:37 mdeboard`: hm not quite what I mae uh

11:37 mean, uh

11:37 if I could figure out how to wrap an exp in braces I'd paste it up for you :)

11:37 sritchie: make a brace -- {} -- then go inside, and hit C-<right> a few times

11:37 that'll grab the s-expressions to the right, one at a time

11:37 mdeboard`: Oh, ok.

11:38 ಠ_ಠ

11:38 I'll give it a chance, but seems like needless complication.

11:38 sritchie: {} :foo (+ 1 2), {:foo} (+ 1 2), {:foo (+ 1 2)}

11:38 or, you can kill (C-k), make some braces, then yank again

11:41 Vinzent: wrap an exp in braces? M-{ ?

11:42 mdeboard`: Didn't work for me

11:42 but re: value mapping, here's a snipper of what I mean

11:42 http://p.mattdeboard.net/cloj.html

11:42 Vinzent: hm, it's working here...

11:43 mdeboard`: amount-tendered is a passed-in arg, and I want `:amount-tendered` to be replaced with `:80` or whatever.

11:43 Vinzent: ah, I have (define-key paredit-mode-map (kbd "M-{") 'paredit-wrap-curly) in my paredit config

11:43 mdeboard`: Do I need to do like (let [x amount-tendered] {:x ....)

11:44 M-{ is move cursor between functions

11:44 (seek whitespace)

11:44 sritchie: https://gist.github.com/1074636

11:44 mdeboard`: no : necessary?

11:45 sritchie: the keyword function converts it to a keyword

11:45 mdeboard`: Ah got it.

11:45 sritchie: ,(-> 100 str keyword)

11:45 clojurebot: :100

11:45 sritchie: ,(keyword "100")

11:45 clojurebot: :100

11:45 mdeboard`: Very cool. Very, very cool. :)

11:45 little more verbose than I'm used to

11:45 (don't hit me)

11:46 sritchie: haha, no worries

11:47 ,(zipmap [:mod :dividend] ((juxt mod (comp int /)) 10 100))

11:47 clojurebot: {:dividend 0, :mod 10}

11:48 sritchie: a less verbose way would be to simply use the number as the key in the map

11:50 https://gist.github.com/1074636

11:50 mdeboard`: Oh.

11:50 facepalm

12:05 Ok, I need some help because recursion is hurting my brain. Please.

12:05 http://p.mattdeboard.net/recursionhelp.html

12:05 I'm trying to rewrite an old "make change" program I wrote originally in Python, in Clojure

12:06 * gfrlog looks

12:06 mdeboard`: Basically you have a "Price", "Amount paid" and "Denominations" (using US denoms here) for this project.

12:07 gfrlog: what's the clos function supposed to do?

12:07 mdeboard`: Well, right now it's just a mechanism that loops over the denominations

12:07 20 = $20 bill, 10 = $10 bill, 5= $5 bill and so one

12:08 so on*

12:08 For each denomination, find the modulo and dividend

12:08 gfrlog: alright. So what do you need help with?

12:09 mdeboard`: Subtract (* dividend denomination) from the Price, then on the next pass, instead of using Price, you use the modulo of the previous denomination

12:10 gfrlog: what should the return value of clos be?

12:10 a map from denominations to counts?

12:10 {20 1, 5 1, 0.10 2}+

12:10 mdeboard`: Yeah, like how many of each bill it took to uh

12:10 gfrlog: s/+/?

12:10 clojurebot: make a note of http://scienceblogs.com/goodmath/2006/11/the_c_is_efficient_language_fa.php it is yet another article about picking c or c++ for performance being naive

12:11 gfrlog: clojurebot: shut up

12:11 clojurebot: Titim gan éirí ort.

12:11 mdeboard`: How many of each bill it took to make change

12:11 gfrlog: mdeboard`: okay. I think this is a natural use for loop

12:11 instead of for

12:11 mdeboard`: Like if the price is $74.99 and I pay $100, how many of each bill does it take to render the difference between 100 and 74.99

12:12 gfrlog: in that case, the argument to clos would be 15.01, right?

12:12 25.01 I mean

12:12 mdeboard`: Right

12:12 gfrlog: okay. Ignoring any potential pitfalls of using floats...

12:13 I would replace the for with

12:13 mdeboard`: yeah

12:13 gfrlog: oh wait we can do this with reduce

12:13 that's cleaner

12:13 mdeboard`: can we? o.O

12:13 gfrlog: are you familiar with reduce?

12:14 mdeboard`: Yeah

12:15 gfrlog: so what makes it maybe slightly tricky is that as we process the sequence of denominations, we have two things to keep track of -- the remaining amount, and the coins computed so far

12:15 mdeboard`: In that I know generally wha tit does. But I'm coming from Python where using reduce is silly. :(

12:15 gfrlog: but that just means our reduce-value needs to be a pair

12:15 its starting value will be [amount {}]

12:15 and we process the list of denoms, updating both parts of the pair as we go

12:16 so the reduce function could be:

12:16 mdeboard`: Whew.

12:16 I definitely need to see that in a snippet

12:16 gfrlog: kay I'll pastie it

12:17 I think it takes some practice to see how to use reduce effectively

12:18 https://gist.github.com/1074657

12:19 so that would go under the (let [denoms ...]), replacing the for

12:19 * mdeboard` throws up

12:19 mdeboard`: I think you just gave me a concussion

12:19 gfrlog: oh dear

12:19 sritchie: try running through it with just one value

12:20 reduce calls the supplied function with the following args, in pairs. So, first, that function gets [amount {}] and the first thing in denoms

12:22 https://gist.github.com/1074659

12:22 here are the first few steps of that first call

12:22 mdeboard`: http://p.mattdeboard.net/nullpointer.html that code threw a null pointer exception

12:23 gfrlog: oh ah ha

12:24 I misused the return value from calc-coins

12:24 mdeboard`: is it supposed to be denoms?

12:24 or?

12:24 gfrlog: one fix is to change calc-coins so it just returns {:mod ..., :dividend ...}

12:25 i.e., instead of {:0.20 {:mod 0.07, :dividend 3}}, return {:mod 0.07, :dividend 3}

12:26 mdeboard`: ya that did it

12:26 it being removing the np

12:27 gfrlog: if you really want the keys to be keywords instead of numbers, you can change (assoc coins denom dividend) to (assoc coins (-> denom str keyword) dividend)

12:27 sritchie: gfrlog: that doesn't quite work, since each mod and dividend knocks out the previous one

12:27 * mdeboard` is looking away while he tries to grok this

12:27 gfrlog: but I think the numbers make more sense

12:27 sritchie: eh?

12:27 mdeboard`: Yeah right now it just returns the dividend

12:27 http://p.mattdeboard.net/dividends.html

12:28 sritchie: ah, never mind

12:28 gfrlog: oh you'd also want to wrap that in (last)

12:28 or (second)

12:28 since ultimately you're only interested in the second part of the reduce value

13:07 mdeboard`: gfrlog: http://p.mattdeboard.net/dividends.html What's "amount-left" in your example?

13:09 gfrlog: mdeboard`: that's what the mod gets assigned to each time

13:09 so...it's the amount left :)

13:11 by the end of the reduction it should be 0

13:12 mdeboard`: u rite

13:15 gfrlog: mdeboard`: is it making sense?

13:15 mdeboard`: Oh, so the line that starts with (fn [[amount-left...) is just an encapsulation. An anonymous function?

13:15 er, not the line, but that block of code

13:15 gfrlog: (fn [...] ...) is the syntax for an anonymous function, yes

13:16 mdeboard`: I'm justgetting hung up on amount-left

13:16 gfrlog: amount-left starts out as the full amount

13:16 mdeboard`: Where is mod getting assigned to it?

13:17 ohhhh

13:17 gfrlog: you see how the if expression will evaluate to one of two vectors?

13:17 mdeboard`: ok

13:17 hang on

13:17 Sorry I slip out of polish notation mode sometimes

13:17 gfrlog: it could be done without the if, but then the return map would have all of the denominations in it instead of just the ones that matter

13:19 mdeboard`: (let [{:keys [mod dividend]} (calc-coins amount-left denom)] --> that's assigning the values of the ... array? dict? ... that's being returned by calc-coins to variables, mod and dividend

13:20 gfrlog: yep. It's syntactic sugar for a couple longer expressions

13:20 mdeboard`: map*

13:20 s/array\?\ dict\?/map

13:20 gfrlog: the longest way to do it is (let [x (calc-coins amount-left denom), mod (:mod x), dividend (:dividend x)] ...)

13:20 mdeboard`: ahhh

13:20 ok

13:20 is that destructuring?

13:21 the first way

13:21 gfrlog: the plain destructuring way to do it is to replace x with a map of pairs, like:

13:21 (let [{amount-left :amount-left, denom :denom} (calc-coins amount-left denom)] ...)

13:22 the way in the code is a shorter sugary version that avoids the repetition

13:22 mdeboard`: is :keys a keyword or what?

13:22 I mean I get that it's a keyword

13:22 gfrlog: yeah, it has special meaning in a destructuring map

13:22 mdeboard`: stupid question

13:22 Yeah that was my questino

13:22 if it had a special meaning :P

13:22 gfrlog: there are I think three keywords that have special meaning there

13:22 :keys, :as, and :or

13:23 :as also works when destructuring a list

13:27 mdeboard`: I feel like I'm still missing something with 'amount-left'. `fn [[amount-left coins] denom` is the setup for an anon func, and I get that. But I don't get the vector-of-vectors [[amount-left coins] denom]

13:27 gfrlog: the function has two arguments

13:27 (any reduce function does)

13:27 the first argument is expected to be a pair

13:27 and we're destructuring it

13:27 * mdeboard` is reading API docs for fn

13:28 gfrlog: so [amount-left coins] is the first argument to the function, and denom is the second

13:28 mdeboard`: so let's say we're on the first pass, and denom == 20, what're the values of [amount-left coins] going to be

13:29 gfrlog: on the first pass it will be equal to the "start pair" that we passed as the second argument to reduce, which is [amount {}]

13:34 mdeboard`: oh, oh

13:34 oh

13:35 lightbulbs, i has htem

13:36 gfrlog: \o/

13:36 amalloy: mdeboard`: just woke up, but this looks like a job for ##(doc reductions)

13:36 sexpbot: ⟹ "([f coll] [f init coll]); Returns a lazy seq of the intermediate values of the reduction (as per reduce) of coll by f, starting with init."

13:36 mdeboard`: amalloy: God please no, I'm just grokking this

13:36 :P

13:36 gfrlog: amalloy: are you contradicting me?

13:36 mdeboard`: nerd fight

13:36 gfrlog: amalloy: or are you saying that reductions is helpful for understanding how reduce works?

13:36 amalloy: gfrlog: the scrollback was long. i skimmed it

13:37 * mdeboard` looks at reductions doc

13:37 gfrlog: mdeboard`: reductions will return for you all the intermediate values of reduce, so that might be a good idea, whether or not it's what amalloy meant

13:37 mdeboard`: speaking of Cloj 1.2, why is only 1.1 available in aptitude?

13:37 * gfrlog has nearly never installed clojure via aptitude

13:38 amalloy: mdeboard`: package managers are always behind on shiny new toys

13:38 mdeboard`: I did, but then just went back and installed from source

13:38 amalloy: mdeboard`: go back and don't install at all; let lein pull it down as a project dep

13:38 mdeboard`: Maybe at a later date

13:38 amalloy: yeah

13:38 no rush on that

13:40 mdeboard`: Yeah forgiving some issues with float, reductions is a big cognitive help

13:41 I also exploded the {:keys [foo bar]} syntax to "the long way"

13:41 gfrlog: mdeboard`: whatever helps. You'll compress it back down after you do it the long way a hundred times.

13:41 mdeboard`: sure

13:41 just like list comprehensions

13:42 amalloy: gfrlog: btw, :strs and :syms also have special meaning in the :keys position

13:42 mdeboard`: so is this recursive?

13:42 Or iterative?

13:42 It seems iterative

13:42 gfrlog: amalloy: I figured I was missing some, but there was nobody around to help :)

13:42 mdeboard`: it's not explicitely recursive

13:43 amalloy: mdeboard`: reduce is certainly implemented recursively

13:43 gfrlog: mdeboard`: using the higher-order-functions in clojure lets avoid using (loop) and explicit recursion 98% of the time

13:43 amalloy: gfrlog: you win this round

13:43 mdeboard`: lol

13:43 oh right I read something about that last night

13:43 maybe in JoC

13:44 gfrlog: amalloy: :strs lets you use :keys with string keys?

13:44 amalloy: yeah

13:44 gfrlog: and :syms is the default behavior?

13:44 amalloy: er

13:44 gfrlog: oh wait

13:44 no

13:44 amalloy: no

13:44 gfrlog: I mix up "symbols" and "keywords" sometimes, thanks to dang other programming languages

13:45 amalloy: &(let [{:strs [a b]} {"a" 1 "b" 2}] [a b])

13:45 sexpbot: ⟹ [1 2]

13:56 amalloy: mdeboard`, you mentioned floats. if you're using floats for this currency problem, let me recommend you do everything with integer pennies instead of fractional dollars

13:57 or, i guess, clojure's rational types would probably be okay

13:57 mdeboard`: i.e. $1 = 100?

13:57 amalloy: yes

13:57 gfrlog: amalloy: I was wondering what common opinion of that was

13:57 I've taken that approach with javascript

13:57 amalloy: $google currency floating point

13:57 sexpbot: First out of 473000 results is: Floating Point Currency

13:57 http://c2.com/cgi/wiki?FloatingPointCurrency

13:57 amalloy: just googled that at random, don't really know if it supports my point

13:57 mdeboard`: reduce

13:57 wrong buffer

13:58 amalloy: gfrlog: javascript doesn't have ints anyway though, right?

13:58 so it hardly matters

13:58 gfrlog: amalloy: correct, but if you only use integer-valued floats then I don't think you can get into trouble

13:58 amalloy: depends if you ever do any division

13:58 gfrlog: right

13:58 amalloy: adding em together you'll be fine

13:59 gfrlog: and multiplying

13:59 amalloy: mmmmm

13:59 gfrlog: by integers :)

13:59 mdeboard`: Did I write out what this function is doing properly?

13:59 http://p.mattdeboard.net/docs.html

13:59 amalloy: doubles don't have as large a range as longs

13:59 so you can run into a problem

14:00 gfrlog: amalloy: right, so you have to make sure you don't have very much money

14:00 I guess overflow would be awfully silent

14:00 there's a bigint library I've used for javascript. I guess that'd be the ultimate solution

14:00 if you like writing a.multiply(b.add(c))

14:01 which of course I do

14:01 amalloy: mdeboard`: i don't buy your last comment

14:01 gfrlog: now that I think about it, if I ever have to do that again I'd probably write a function called sexp for which I can sexp("(* a (+ b c))")

14:02 mdeboard`: amalloy: Me either, hence the (???)

14:02 amalloy: if i start with ten cents, the second branch of the if will be hit for all the denominations until you get to dimes

14:02 gfrlog: cause the only way you could slow down a bigint library is with eval?

14:03 gfrlog: amalloy: because premature optimization is evil :P

14:03 actually eval wouldn't even work there would it? since you'd lose the scope. Would have to be pre-processed, which I wouldn't mind doing

14:04 if there's enough arithmetic

14:04 amalloy: gfrlog: javascript eval has access to lexical scope

14:05 gfrlog: amalloy: right. So if sexp is defined somewhere else...

14:05 amalloy: ummm...? just define sexp to return a string, and eval that string

14:05 gfrlog: so repeat the call to eval everywhere

14:06 I see

14:06 amalloy: but writing a sexp->javascript precompiler is probably simpler

14:06 gfrlog: and avoids the eval

14:07 mdeboard`: How about extracting the final value of that function? I assume there's a more efficient way than: `(def result (first (rest (last (clos 1693)))))`

14:07 amalloy: well, second is (comp first last)

14:08 gfrlog: amalloy: why is he using reductions if all he wants is the final value?

14:08 dnolen_: mdeboard`: thanks, nice example of mutually recursive yield in Python. As you said that is crazy slow in Python.

14:08 amalloy: er, (comp first rest)

14:08 mdeboard`: oh, right

14:08 derp

14:08 forgot to take out reductions :)

14:08 gfrlog: ah

14:09 I assumed since it was still there amalloy must have been recommending you keep it

14:09 amalloy: mdeboard`: do you care if the keys of the map are in order? they probably are in your impl, but it's only coincidental

14:09 mdeboard`: dnolen_: You're welcome

14:09 amalloy: Not really, but I suppose I should.

14:11 amalloy: if so you should either use a sorted-map (since sorting by key is what you want) or a vector of pairs that you just append to

14:12 though it probably sorts in reverse order? ##(into (sorted-map) [1 4 9 2]) vs ##(into (sorted-map-by -) [1 4 9 2])

14:12 sexpbot: (into (sorted-map) [1 4 9 2]) java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Integer

14:12 (into (sorted-map-by -) [1 4 9 2]) java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Integer

14:12 amalloy: mutter

14:13 mdeboard`: baby steps

14:13 premature optimization chat

14:13 gfrlog: based on the first word of your last two statements I'd say this is a conversation about infants.

14:14 mdeboard`: gfrlog: Based on that statement I'd say you work on machien learning

14:14 gfrlog: ha

14:30 amalloy: mdeboard`: https://gist.github.com/1074808 is a version that seems to involve less tedious bookkeeping

14:31 and (make-change 167/100) yields {:penny 2, :nickel 1, :dime 1, :quarter 2, :dollar 1}, demonstrating that it works and that order isn't maintained :P

14:33 gfrlog: amalloy: no YOU win this round

14:33 mdeboard`: I dropped it into my clj and commented it out, once I've got gfrlog's version snuggled in my brain I'll look at yours

14:35 (assoc foo x y) -> (def foo {x y}) ?

14:36 gfrlog: nope

14:36 it associates the key x with the value y in the map foo

14:36 amalloy: mdeboard`: def has side effects, so very few built-ins are equivalent to a def

14:36 gfrlog: &(assoc {:a 2 :c 4} :b 5)

14:36 sexpbot: ⟹ {:b 5, :a 2, :c 4}

14:36 gfrlog: &(assoc {:a 2 :b 12} :b 5)

14:36 sexpbot: ⟹ {:a 2, :b 5}

14:37 mdeboard`: ,(assoc {:a 2 :b 12} :b 5)

14:37 clojurebot: {:a 2, :b 5}

14:37 mdeboard`: :')

14:37 gfrlog: we both picked twelve because we're soul mates?

14:37 mdeboard`: lol no, just beign smug about knowing the syntax

14:38 Dunno if either of you are familiar with Python, but it seems like (assoc map key val) is analogous to Python's dict key-val pair setting

14:38 dnolen_: mdeboard`: amalloy: my version, https://gist.github.com/1074818

14:38 mdeboard`: e.g. dict = {} \ dict['foo'] = 'bar' \ dict --> {'foo': 'bar'}

14:39 1e-6 ?

14:39 amalloy: gfrlog: what do you think about https://gist.github.com/1074808 - i'm not sure if the threaded version is more or less readable

14:39 mdeboard`: is that engineering notation?

14:39 amalloy: scientific

14:39 (though they happen to be the same here)

14:39 mdeboard`: that too

14:39 amalloy: mdeboard`: yes, assoc is like that, except without side effects

14:40 gfrlog: oh threaded. I was thinking "why the heck is he making this multi-threaded??"

14:40 amalloy: oh. the threaded version is also totally wrong

14:40 never mind, sigh

14:40 mdeboard`: persistence > perfection amalloy

14:40 unless you're actually perfect then persistence is unnecessary

14:41 gfrlog: mdeboard`: it's different from python dicts because clojure maps are immutable

14:41 mdeboard`: right

14:41 I mean it's impossible to have a REAL 1:1 correlation but the spirit of my question isn't as deep as that.

14:41 gfrlog: gotcha

14:42 mdeboard`: state mutability notwithstanding

14:42 god Joy of Closure has an absolutely epic explanation of state

14:42 I might go back and re-read it

14:42 amalloy: mdeboard`: dnolen's used update-in, which is a fantastic tool for working with maps. keep it in mind

14:43 (and it goes great with fnil)

14:43 gfrlog: fnil: there's always something else I've forgotten exists :|

14:43 mdeboard`: Ya I've got them both appended at the end of my clj, commented out

14:50 Here's my problem, I think gfrlog's solution is pretty straightforward now that I grok it, but I have trouble thinking in the way that would be required to come up with such a solution. Recursive thinking, i guess? I mean, once you've broken the problem down atomically, what element do you start with to start building a solution in your head?

14:50 dnolen_: mdeboard`: amalloy: and because I hate slow code, https://gist.github.com/1074818

14:51 gfrlog: mdeboard`: I think of reduce whenever I have a collection of elements (denominations) that I need to loop over, while keeping track of something

14:52 amalloy: dnolen_: the 1e-6 check looks kinda silly to me. if the amount ever gets below 0.01 due to a rounding error, you'll get a NPE during subtraction

14:52 so i'd put the termination test in the drop-while

14:52 (and use ints instead of doubles, especially if you care about performance)

14:53 dnolen_: amalloy: ints for currency?

14:53 amalloy: yes

14:53 dnolen_: 1e-6 check is straight out of what I've seen done in graphics code.

14:53 amalloy: if you use floating-point at a bank they murder you in the spot

14:53 *on

14:53 dnolen_: amalloy: did know that, never done any financial work.

14:54 did not.

14:54 gfrlog: amalloy: any clue what they do when they want to keep track of fractional cents?

14:54 amalloy: dnolen_: sure, in general for testing floats you want to use a delta like 1e-6

14:54 but for money you should use ints, and the way you're using drop-while the test could cause NPE on rounding error *anyway*

14:55 gfrlog: work with integer thousandths of cents :P

14:55 gfrlog: amalloy: that was my guess

14:55 dnolen_: I think when handling money it's always cleanest to be discrete

14:55 dnolen_: amalloy: Yeah, I see what you mean about the 1e-6 test and rounding error.

14:56 gfrlog: floats are good for things that don't have to be perfectly accurate

14:56 amalloy: gfrlog: that is both edutational and punnerific

14:56 dnolen_: suddenly this is an exercise on Enterprise Financial Programming instead of a lesson on recursion ;)

14:56 gfrlog: amalloy: I strive to edutate!

14:56 amalloy: haha ouch

14:57 mdeboard`: amalloy: Why do you use a vector of vectors instead of a map in your example?

14:57 TimMc: gfrlog: and wash your hands afterward

14:57 amalloy: to preserve ordering

14:57 gfrlog: TimMc: :)

14:57 mdeboard`: ah ok

14:57 amalloy: if the map happened to be 10+ elements (say we track fifties and half-dollars), it no longer (coincidentally) preserves order

14:58 mdeboard`: so how do you retrieve the value of, say, :twenty?

14:58 (I'm trying this stuff out in repl before I ask btw)

14:59 gfrlog: mdeboard`: :twenty is a function that can do that

14:59 amalloy: it's in change-denom's destructuring-let

15:01 mdeboard`: Oh, gotcha. Smart

15:02 amalloy: dnolen_: out of curiosity, is the repeated-subtraction faster than division because the numbers are small enough?

15:02 or is it just more convenient to write?

15:03 it seems to me that calling update-in more times ought to incur an uncomfortable about of memory allocation, but i guess i don't know whether that's more expensive than division

15:03 * gfrlog thinks that sounds right

15:03 mdeboard`: honestly I don't think order matters here

15:03 amalloy: mdeboard`: of the final result, no. but for the list of denominations, yes

15:04 mdeboard`: lol, got it. Why does learning a new language & programming paradigm turn me into a huge idiot

15:04 amalloy: ~#19

15:04 clojurebot: 19. A language that doesn't affect the way you think about programming, is not worth knowing.

15:05 mdeboard`: A+

15:06 so yeah mapping hashes they k/v pair I assume, which tosses out any ability to sort on keys at a low level?

15:06 dnolen_: amalloy: is this more sound? https://gist.github.com/1074818

15:06 mdeboard`: except sorted-map-by

15:07 also as long as they're in order in the original list, isn't reduce always going to walk over them in order?

15:07 gfrlog: mdeboard`: yes, reduce goes in order

15:07 mdeboard`: it's just once they're assoc'd into the map then they're not necessarily in order. But if they're mapped I can just call the key to return the value, so order doesn't really matter

15:08 (aka the whole point of maps)

15:08 vis a vis speed

15:08 amalloy: dnolen_: hah, that's a clever way to use rename-keys

15:08 * amalloy didn't even know rename-keys existed

15:09 mdeboard`: gist doesn't either apparently

15:09 amalloy: github syntax-colors clojure code at random, or something like it

15:09 mdeboard`: lol, what.

15:10 I just mean that I guess "rename-keys" isnt in its table of identified built-ins

15:10 amalloy: mdeboard`: but make-change is?

15:10 mdeboard`: well once it's defn'd

15:10 gfrlog: I've been using clojure.core/make-change for months now

15:10 amalloy: i'd be astonished if they were parsing the source for defns

15:11 dnolen_: mdeboard`: probably because rename-keys is in clojure.set

15:11 amalloy: dnolen_: anyway, that looks like it passes muster for banks :)

15:11 dnolen_: amalloy: sweeeet

15:11 amalloy: nah, because drop-while isn't colored either

15:11 mdeboard`: probably a bit of code in gist source that puts "foo" in ID'd functions table when it sees `defn foo`

15:11 dnolen_: oic

15:11 amalloy: maybe so

15:12 https://gist.github.com/1074857 indicates that they have no such defn parser

15:13 mdeboard`: I suspect that's an engineering oversight

15:13 on forked gists

15:13 amalloy: https://gist.github.com/ba4079175d8d5eda81cb

15:13 mdeboard`: or on edits

15:14 * amalloy can do this all day. github's parser is pretty hard to predict

15:14 mdeboard`: huh. I bet they cache them :)

15:14 amalloy: haha prepare to be strangled

15:15 mdeboard`: https://gist.github.com/1074861

15:15 gfrlog: nerd fight!

15:15 mdeboard`: https://gist.github.com/1074862

15:15 I win :)

15:16 amalloy: what's your point?

15:17 mdeboard`: lol just that they cache function names :P Look I'm clearly the dumbest person in this chat room, I need this.

15:17 amalloy: https://gist.github.com/ba4079175d8d5eda81cb is a disproof :P

15:17 mdeboard`: Huh

15:17 I guess it IS random!

15:17 amalloy: *chuckle*

15:19 gfrlog: maybe it dispatches on the hash code of the symbol modulo some value

15:19 mdeboard`: Which is unreliable enough to be indiscerinable from random

15:20 But yeah maybe they drop [^a-zA-Z0-9]

15:20 or something, who cares, I'm trying to learn Clojure

15:20 :)

15:22 (I was joking, btw, you guys have been a huge help)

15:48 gfrlog: amalloy: it just occurred to me that a third no-eval-or-precompile option for the javascript problem could be done by passing the variables to sexp: sexp("(+ %1 (* %2 %3))", a, b, c)

15:48 man it took a lot of effort to type those commas...

15:51 dnolen_: mdeboard`: amalloy: re, arithmetic vs division, yeah that was silly. https://gist.github.com/1074818, code is very short now, updated one last time.

15:55 gfrlog: there's not anything like clojure.core/*rand* is there?

15:59 amalloy: gfrlog: clojure.core/inc seems to meet all of the requirements you've stated so far

16:00 gfrlog: amalloy: you mean being a qualified symbol?

16:00 in the clojure.core ns?

16:02 mdeboard`: Hrm, prob a dumb question but I uninstalled clojure, to allow lein to install. I did "lein self-install" but er

16:03 No clojure dl? idgi

16:03 gfrlog: mdeboard`: yes clojure dl. odxt

16:03 amalloy: mdeboard`: it gets downloaded in projects you start

16:03 gfrlog: mdeboard`: try "lein repl"

16:04 mdeboard`: Oh

16:04 So clojure isn't dl'd system-wide, just in particular projects?

16:04 amalloy: right

16:05 gfrlog: mdeboard`: I think it keeps a version in your maven dir that it copies to new projects

16:05 mdeboard`: Kind of like rvm I suppose

16:05 amalloy: or virtualenv

16:05 kinda

16:05 mdeboard`: kinda but wihtout the path hack

16:05 amalloy: i don't really know anything about python or ruby, so read these analogies at your own risk

16:05 mdeboard`: haha

16:07 so I just do lein self-install for each project or just one time for the system?

16:07 amalloy: just once

16:08 gfrlog: mdeboard`: "lein new foobar" creates a new project for you

16:16 jimi_hendrix: is there a clojure lib for asynchronous server sockets, or should i poke arond the java library?

16:16 gfrlog: jimi_hendrix: (or aleph "I don't know what I'm talking about")

16:17 jimi_hendrix: gfrlog, should i be reading that as a lisp statement :P

16:17 gfrlog: sorta

16:19 amalloy: (inc aleph)

16:19 sexpbot: ⟹ 1

16:20 mdeboard`: lol

16:20 gfrlog: amalloy: is there a sexpbot karma read command?

16:20 jimi_hendrix: lol

16:20 gfrlog: (deref amalloy)

16:20 amalloy: gfrlog: yes, but afaict it's broken

16:21 $help karma

16:21 sexpbot: amalloy: Checks the karma of the person you specify.

16:21 mdeboard`: $help mail

16:21 sexpbot: mdeboard`: Send somebody a message. Takes a nickname and a message to send. Will alert the person with a notice.

16:21 Scriptor: $karma Scriptor

16:21 amalloy: gfrlog: feel free to fork&fix it for me, cause i don't see what's broken

16:21 gfrlog: amalloy: it should work the way Scriptor just used it?

16:21 amalloy: yeah

16:21 gfrlog: okay

16:21 Scriptor: does it not print anything if the karma is 0?

16:22 amalloy: $karma aleph

16:24 Scriptor: in clojure's source, what does the variable 'sv' usually stand for?

16:24 I'm guessing something like seq value

16:24 mdeboard`: The leiningen tutorial seems really incomplete

16:24 Big gaps

16:25 mids: how would I best go about attacking this stacktrace? https://gist.github.com/1074930

16:26 mdeboard`: I mean, for me. Like, so I put clojure-contrib in my project's project.clj. Do I just automatically have that? Or do I need to run another command? lein install? I did that and it says it can't find change__init.class or change.clj on my classpath.

16:26 gfrlog: mdeboard`: lein deps will populate your lib dir

16:27 mdeboard`: aha

16:27 Scriptor: mdeboard`: there's a clojure tutorial about setting up slime/swank/lein...buuut it's for windows :p

16:28 mdeboard`: I mean, I just really want a step-by-step walkthrough. lein deps doesn't get mentioned until the very end of the third PARAGRAPH in the second section of the tutorial

16:32 I'm spoiled by python, sorry.

16:42 amalloy: Scriptor: i wouldn't be surprised if it were a sort of hungarian: "this variable has already had seq called on it"

16:44 Scriptor: amalloy: hmm, not sure it's the result of seq(), it's set by sval() (there's the answer for the name, I guess)

16:44 amalloy: ah

16:44 Scriptor: for reference: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LazySeq.java#L37

16:46 technomancy: for the record, the next version of lein will automatically detect changes to :dependencies in project.clj and run deps for you. you can turn on this behaviour in current versions with :checksum-deps true in project.clj

16:46 mdeboard`: ^^

16:46 mdeboard`: technomancy: smashing

16:47 technomancy: actually I could use some more folks testing that feature as the only reason it's not on by default is it hasn't seen wide use

16:47 but if I don't tell people about it, it will never see wide use.

16:48 mdeboard`: That seems like something that should be on by default for new users

16:48 imo

16:48 as a new user

16:48 technomancy: yes, assuming it works correctly

16:48 which I have not yet determined

16:49 hence the need for testing

16:50 * gfrlog imagines technomancy as GLaDOS in Portal

16:51 hiredman: http://www.thinkwithportals.com/music.php "songs to test by"

16:51 keithwyss: technomancy: Is it a plugin currently?

16:51 technomancy: keithwyss: no, it's built-in. just needs :checksum-deps true in project.clj to enable it

16:52 gfrlog: hiredman: :)

16:52 technomancy: and if you're in the mood for testing features that will hopefully be default later, you could also add :local-repo-classpath true to project.clj

16:52 that will make the classpath reference ~/.m2 instead of copying everything into lib

16:53 keithwyss: Cool. I'll jot those down.

16:53 mdeboard`: Editing my newb project.clj right now.

16:53 jimi_hendrix: where exactly does lein pull deps from?

16:54 technomancy: clojurebot: look at me still talking when there's science to do

16:54 clojurebot: science is http://sunpig.com/martin/images/2008/10/iwilldosciencetoit.jpg

16:54 technomancy: clojurebot: a thousand botsnacks

16:54 clojurebot: Titim gan éirí ort.

16:54 technomancy: jimi_hendrix: by default: http://clojars.org and http://search.maven.org

16:54 wilfredh: is there a compojure equivalent of Django's reverse()?

16:55 i.e. something that takes a function and returns the corresponding URL

16:55 gfrlog: doubt it

16:55 not sure that really makes sense for compojure

16:56 zakwilson: I'm looking at sandbar.auth, and it seems to have a good thing going wtih the ability to have a role-based security policy. I'm a bit confused about how I might use it to do something more fancy though, like say that the person editing an item must own that item (or be an admin).

16:56 wilfredh: I must be missing something -- why doesn't it make sense?

16:57 gfrlog: wilfredh: you're using (defroutes ...)?

16:57 amalloy: well, it assumes a one-to-one correspondence between functions and URLs, which seems pretty foreign

16:57 technomancy: gfrlog: http://p.hagelb.org/cake.gif

16:58 gfrlog: technomancy: I want to elect that president.

16:58 wilfredh: gfrlog: yes, I'm using defroutes

16:58 amalloy: it also supposes that compojure does a lot of things it doesn't actually do, like keep track of the routes in a table somewhere once you define them

16:58 keithwyss: One thing that I'd like to see in lein is the ability to enter some tags like :latest or :latest-stable in project.clj and have a plugin rewrite the project file so that a developer doesn't have to check every version.

16:58 gfrlog: wilfredh: everything amalloy said.

16:58 wilfredh: not to mention a lot of routes are globby and so don't correspond to just one url

16:58 keithwyss: I'd be willing to take a stab at it assuming there's not something like this already I missed out on.

16:58 amalloy: keithwyss: :dependencies [[clojure "[1.2.0,)"]]

16:59 technomancy: keithwyss: it's a lot easier to check now with lein search too.

16:59 Scriptor: noob question, but is there a lein command to have it update itself? I always suck at googling for that one

16:59 amalloy: lein upgrade

16:59 Scriptor: ah

16:59 gfrlog: this is awesome I just ran "lein upgrade" and it worked.

16:59 Scriptor: damnit, not available on windows

17:00 gfrlog: I guess I shouldn't have celebrated. It was insensitive to windows users.

17:00 keithwyss: amalloy: what does "[1.2.0,)" mean. I'm not used to seeing parens that aren't matched.

17:00 amalloy: $google mathematics interval notation

17:00 sexpbot: First out of 710000 results is: Interval Notation

17:00 http://regentsprep.org/REgents/math/ALGEBRA/AP1/IntervalNot.htm

17:01 gfrlog: I figured it meant the version number was winking

17:01 technomancy: keithwyss: there's a link in "lein help tutorial" about version ranges

17:01 Scriptor: is 1.6.1 the latest version number? I want to try technomancy's automatic dep installation

17:01 technomancy: Scriptor: it is

17:01 keithwyss: Thanks for the help. That's exactly what I wanted.

17:02 wilfredh: gfrlog: Django handles the fact that there isn't a one-to-one correspondence. I can do {% url app_name.views.foo id=3 %} and Django replaces it with /foo/view/3 rather than me hard-coding URLs everywhere. But if I can't do this, never mind.

17:03 technomancy: Scriptor: but that feature is in 1.5 iirc

17:04 gfrlog: wilfredh: I think it sounds theoretically possible, if instead of how defroutes works it had you just describe pairs of routes and functions. But because defroutes essentially creates inline (anonymous) functions, I don't think it's compatible. In any case I don't think it exists right now.

17:04 wilfredh: I agree it'd be nice though.

17:05 Scriptor: technomancy: must have missed it before, does it install the dependencies whenever you compile?

17:05 technomancy: Scriptor: it looks at the checksums every time code has to be evaluated inside the project's context

17:08 Scriptor: technomancy: checksums for the dependency?

17:09 Scorchin: Can someone help explain the following code for me please? It's being passed a "board" similar to a X by Y grid: http://pastebin.com/40Lp7EYk

17:09 zakwilson: The idea of being able to link to a function rather than a URL seems higher-level than Compojure, as Compojure doesn't have a very rigid idea of what sort of thing a route is connected to.

17:11 technomancy: Scriptor: right; it serializes :dependencies and :dev-dependencies to a string and checksums that

17:12 gfrlog: zakwilson: I can imagine an alternative to (defroutes) that provides reversal without too much trouble

17:12 amalloy: Scorchin: whatever it's doing, it's written badly in a few ways, making it hard to understand

17:12 gfrlog: yeah that's pretty weird code

17:12 amalloy: it seems to be checking whether it is the case that all but the first and last column are nil

17:12 Scriptor: technomancy: ah! But how does lein know when code is evaluated? Sorry, not very familiar with how it works

17:12 Scorchin: amalloy: I'm trying to imitate it to build a way to check if a tetris grid has hit a "game over" state

17:13 zakwilson: gfrlog: so can I, but it requires a more rigid structuring of the app that Compojure currently requires. That may not be in keeping with the project's goals.

17:15 amalloy: totally agree there. i wonder if moustache has that more rigid structure? i haven't used it but have heard that sort of thing

17:16 ibdknox: Noir, doesn't really help here, but if you want a stricter structure, more akin to Rails or Django, look at wakeful

17:16 it maps urls directly the namepsace structure

17:16 to*

17:16 gfrlog: zakwilson: I think the added structure would be pretty isolated

17:16 zakwilson: say if the reverse-routing function were not a built in compojure function but just a function that's returned from (def-reversible-routes)

17:16 technomancy: Scriptor: things like repl, test, and compile have to run code in your project's process to have access to its dependencies

17:17 zakwilson: gfrlog: then do it. It sounds useful; I'd probably start using it right away in production client code if it didn't require me to make many changes.

17:18 gfrlog: oh I'm not THAT motivated, I just wanted to make the point that I don't think it's incompatible with compojure :)

17:19 hiredman: https://github.com/hiredman/graft

17:19 zakwilson: Damn. I was hoping somebody would do it for me so I don't have to figure out a good way.

17:21 ibdknox: zakwilson: I guess you assume the URL is going to change a lot?

17:22 zakwilson: ibdknox: no. I just don't like code that generates anything with semantic meaning using string concatenation.

17:23 gfrlog: :)

17:23 yeah it lets your bugs leak farther...

17:23 zakwilson: Well, string concatenation can happen somewhere, but I don't want magic strings in my code.

17:24 ibdknox: lol

17:24 gfrlog: zakwilson: exactly

17:24 ibdknox: I don't see the difference really

17:24 hiredman: you prefer magic code?

17:24 gfrlog: ibdknox: the difference is what happens when you make a typo

17:24 ibdknox: gfrlog: it's a location

17:24 gfrlog: locations are inherently strings

17:24 in this case

17:25 hiredman: no, I don't :)

17:25 but the solution of reverse calling a url is no different than using its string representation :)

17:25 zakwilson: To give a simple example, (go-home) is better than (redirect "/") because it's possible that the app might end up being somewhere other than the root... is directory even the right word here? You know what I mean though.

17:25 gfrlog: ibdknox: just because they're exposed as strings doesn't mean that's how you have to refer to them as a programmer

17:26 ibdknox: zakwilson: that is fair

17:26 zakwilson: usually that's taken care of by setting an app root though

17:26 zakwilson: Even though right now (defn go-home [] (redirect "/"))

17:26 Sure, that's another way to do it

17:27 ibdknox: gfrlog: sure, you don't have to, but I'm not sure I see the value in the abstraction, that's all :)

17:29 gfrlog: ibdknox: one value is that if you're using vars instead of strings, the compiler can point out your mistakes

17:30 ibdknox: gfrlog: that's fair

17:31 gfrlog: it becomes more personal preference I think

17:31 ihodes: what's a really cool data structure that can be useful to hold something a sparse matrix normally would?

17:32 hiredman: a map?

17:32 amalloy: hiredman: no, he said really cool

17:34 wilfredh: I've always thought a Fibonacci heap was pretty cool</tongue-in-cheek>

17:40 gfrlog: finger trees of vectors of arrays of refs

17:40 ibdknox: lol

17:40 ^^ best solution there

17:42 ihodes: hiredman: a map is basically the underlying implementation of a sparsematrix (can't think of a better one, anyway).

17:42 you guys are no fun :P

17:43 there a good # on freenode for data structures?

17:44 hiredman: by the way, i'm using visor mode in iterm now, and i love it.

17:45 gfrlog: ihodes: what is "something a sparse matrix normally would"?

17:45 what does .lein-failures do?

17:46 hiredman: tracks test failures for lein retest

17:46 dnolen_: ihodes: ITerm2 is pure awesomeness, I'm giving Cocoa Emacs the boot.

17:46 gfrlog: lein retest will run all tests listed in .lein-failures?

17:47 technomancy: gfrlog: aye

17:47 gfrlog: (inc technomancy)

17:47 sexpbot: ⟹ 11

17:48 ihodes: dnolen_: i've been using emacs -nw forever. i was too much of a snob regarding the ugly frames in cocoa-emacs. also. i'm a bit of a showsman.

17:48 hiredman: I think my fullscreen cocoa-emacs is rather fetching

17:49 ihodes: gfrlog: provide the same sort of access and representation of a matrix (just 2d in my case, but nD would be nice) without having to store empty positions

17:49 gfrlog: ihodes: I'm not sure why you find a map so disappointing

17:49 ihodes: hiredman: it probably is. and i bet it can handle real themes, too. which mine can't (AFAIK...) so I just set the colors i like with iTerm's profiles. jank.

17:49 gfrlog: i don't at all! i love maps

17:50 gfrlog: i just was wondering if there was anything different/weird/interesting

17:50 gfrlog: doesn't have to be better (could there even be a better data structure for that use case?)

17:50 gfrlog: in fact, the structure would probably be isomorphic to a map in order to get similar performance.

17:51 dnolen_: ihodes: ITerm2 has 256, Emacs colors themes look perfect.

17:51 ihodes: dnolen_: how do you get emacs to display those themes? my themes don't match up; they use my profiles' colors, and swap them around sometimes...

17:52 dnolen_: i tried zenburn, for e.g., but it just mixed up the colors i had already set from iTerm's GUI

17:52 dnolen_: ihodes: Preferences > Profiles > Terminal > Report Terminal Type: xterm-256color, zeburn looks flawless

17:53 with ITerm2 mouse reporting you can even click to set the cursor position in Emacs.

17:58 ihodes: dnolen_: IT WORKS. the profile i was using was reporting just xterm, for some reason i guess that's the default. thanks :)

17:59 dnolen_: ihodes: no problem

18:14 mdeboard`: technomancy: This might interest you re: science http://i.imgur.com/W7Fcl.jpg

18:39 zodiak: so, I understand from last night that a quote means 'do not execute' or stop execution, why then in require does it have ' before a symbol (or list, or etc etc) ?

18:42 opqdonut: well you don't want to fetch the value in the variable foo.bar.baz

18:42 you want to give the symbol foo.bar.baz to identify the namespace

18:42 require could work with strings too, for example

18:44 zakwilson: or you might actually want the value of a variable: (let [the-thing-to-require 'clojure.contrib.sql] (require the-thing-to-require))

18:44 ihodes: zodiak: also, for instance, if you tried (first (1 2 3)), you'd be "calling" 1. which can't be called, as it's not a function. so you want to prevent its evaluation with a quote: (first '(1 2 3))

18:44 gfrlog: or use a vector literal :)

18:45 ihodes: gfrlog: grrrrrrrr. the idea was to explain the ' :P

18:45 zakwilson: I have some code that does (apply require the-list-of-requirements)

18:45 gfrlog: ihodes: I know I know I know...

18:45 zakwilson: The ' means "I want the NAME foo, not the value of foo"

18:46 zodiak: well, part of my confusion was thinking that 'symbol was basically saying ' makes things as a 'symbol'

18:46 zakwilson: It's a symbol either way, but the ' means you want the symbol itself, not the thing it references.

18:46 zodiak: so, seeing it as '(1 2 3) and then getting told (in the books) that's a vector literal didn't help

18:47 ihodes: zodiak: [1 2 3] is a vector

18:47 zodiak: zakwilson: well, I come from the whole 'a symbol is a symbol' .. there is no difference between what the symbol points to and the symbol itself

18:47 ihodes: zodiak: '(1 2 3) is a list.

18:47 zodiak: ihodes: correction then. lit.

18:47 ihodes: zodiak: (1 2 3) is a function application

18:47 zodiak: list.

18:48 ihodes: zodiak: applying the function 1 to the operands 2 and 3. but 1 isn't a function... so you get a kaboom.

18:49 zodiak: ihodes: gotcha. although I still fail to see the logical distinction between what a symbol references and the symbol itself, since a symbol of 'hello can only ever have hello (at least, that was my mathematical understanding of symbols :)

18:49 ihodes: zodiak: (quote (1 2 3)) tells the reader not to try to look up 1 in the local or global scope, and to not treat it as a function. instead, ' (or quote) tells the reader that the following symbol or sexp should be taken as a literal whatever. and not evaluate it.

18:49 gfrlog: ihodes: I don't think it's the reader, I think it's the compiler

18:49 ihodes: zodiak: the thing to understand is that in functional lisp, everything has a value. symbols are all references to values of literals

18:50 gfrlog: ah yeah, sorry.

18:50 zodiak: huh. symbols have values eh. okay. interesting :)

18:50 zakwilson: You can have a symbol that isn't a reference to anything.

18:50 gfrlog: zodiak: it's a bit more complex than that

18:50 ihodes: zodiak: right, so first refers to the function first--think of the compiler as replacing alllll references in your code to first with the actual code for the definition of the function.

18:51 zodiak: so, that makes the require more understandable. I think :)

18:51 ihodes: zodiak: and doing that recursively with everything it find when it looks up the symbols it encounters. it can't, of course, replace values.

18:51 zakwilson: ,'this-is-an-unbound-symbol

18:51 clojurebot: this-is-an-unbound-symbol

18:51 ihodes: zodiak:

18:51 zakwilson: ,this-is-an-unbound-symbol

18:51 clojurebot: java.lang.Exception: Unable to resolve symbol: this-is-an-unbound-symbol in this context

18:51 ihodes: ,`(~'hah)

18:51 clojurebot: (hah)

18:52 ihodes: cause i'm a jerk. anyway, need to hack some

18:52 l

18:53 jimi_hendrix: lien deps wont download clojure-contrib for me. it complains about a missing artifact. is this to be expected?

18:53 * gfrlog feels a little dirty that that conversation finished without mention of vars

18:53 gfrlog: jimi_hendrix: what's it look like in the project.clj?

18:54 jimi_hendrix: gfrlog, [org.clojars.jhowarth/clojure-contrib "1.2.0-RC3"] (copied from clojars)

18:55 gfrlog: try [org.clojure/clojure-contrib "1.2.0"]

18:55 jimi_hendrix: gfrlog, oh nvm i found it

18:55 i just got it to work

18:55 gfrlog: okay

19:00 ihodes: gfrlog: what would you explain re: vars? I don't know how much they'd add

19:00 gfrlog: to zodiak's understanding

19:00 gfrlog: ihodes: I know it could be confusing to a beginner, but they're definitely relevant to the topic

19:01 ihodes: gfrlog: i mean, how would you explain it? i can't think of a great way to

19:03 gfrlog: ihodes: I think I would say that the compiler, when processing a non-quoted symbol, first checks the local scope (i.e., let and fn-arguments), and if it doesn't find the symbol there then it checks the current namespace to see what var the symbol refers to. The compiled code then contains a reference to that var (I think), the value of which can vary (but normally doesn't)

19:04 so for example saying that the compiler replaces the symbol with the source of the function could be quite misleading

19:05 ihodes: gfrlog: to be fair, i didn't say that happened. i just think it's a good way to think about it to begin with. but you're right, more explicitely explainng vars could be useful. i think, though, you'd then need to explain other reference types like refs.

19:05 hiredman: the movement from the substitution model to the environment model is a big one

19:05 move

19:06 gfrlog: hiredman: so do you think it's helpful to discuss vars with beginners?

19:06 ihodes: gfrlog: actually, i think first you'd need to explain the difference between the reader and compiler

19:06 gfrlog: ihodes: true

19:06 ihodes: my example/explanation conflates them. which i think is actually useful for a beginner, for reasoning about code

19:07 hiredman: gfrlog: they have to learn about them sometime

19:07 zodiak: speaking as a beginner (to clojure anyway) going -that- in depth is going to turn off people

19:07 gfrlog: I did a lot with clojure before understanding reader vs compiler

19:07 ihodes: gfrlog: and, to be clear, i'm totally interested in having this conversation. i'm very interested in teaching more people about Clojure, so if it seems like i'm challenging you it's not because i'm being a jerk, but trying to figure it out

19:07 gfrlog: I'm definitely not sure about this either way, which is why I didn't really interject about it during the conversation

19:08 ihodes: hiredman: that's like saying "you've got to learn about eax sometimes. might as well start with x86"

19:08 hiredman: there needs to be an abstract understanding first, if you want to quickly get up to speed. else you do need to start very low and move up.

19:09 hiredman: ihodes: *shrug*

19:09 ihodes: it's useful to think about a program as text, and then think of what happens when you run it as text transformation. then imagine the computer is running your transformed text. and, on a level, that is what's happening. then you can start to understand the different levels of indirection and transformation.

19:10 hiredman: i feel ya

19:12 pcavs: $findfn -1 1

19:12 sexpbot: [clojure.core/unchecked-negate clojure.core/-]

19:12 pcavs: $findfn 100 100

19:12 sexpbot: [clojure.set/union clojure.set/intersection clojure.set/difference clojure.core/time clojure.core/dosync clojure.core/long clojure.core/short clojure.core/+ clojure.core/* clojure.core/with-loading-context clojure.core/doto clojure.core/float clojure.core/macroexpan... http://gist.github.com/1075077

19:13 ihodes: ,(Math/abs -1)

19:13 clojurebot: 1

19:26 wilfredh: I'm getting an error "Call getNextException to see the cause." but trying to call that with (.getNextException e) just gives me "No matching field found: getNextException for class java.lang.Exception"

19:26 what am I doing wrong?

19:27 hiredman: e is most likely a runtime exception wrapping whatever exception has the getNextException method

19:28 wilfredh: how would I unwrap it?

19:43 ah, I needed getCause

20:00 jimi_hendrix: i am :require ing clojure.contrib.string, but it says split is not being found. what is up?

20:02 sritchie: jimi_hendrix: make sure you use the prefix you specified --

20:02 jimi_hendrix: sritchie, prefix?

20:02 sritchie: two things -- one, trying requiring clojure.string

20:03 the two options for this sort of thing are use and require

20:03 use pulls all functions from the use'd namespace into the current namespace -- (use 'clojure.string) (join "," [1 2 3]), for example

20:04 require allows you to assign a prefix to functions from that namespace -- (require '[clojure.string :as s]) (s/join "," [1 2 3])

20:04 jimi_hendrix: ah

20:04 i was using this to include it: (ns your-namespace

20:04 (:require clojure.contrib.string))

20:04 sritchie: yeah, that makes everything available with the full namespace as a prefix

20:04 jimi_hendrix: i see

20:04 zodiak: jimi_hendrix: for the love of the gods, don't get people started about ' before the module again ;p

20:04 sritchie: (:require clojure.string) lets you do (clojure.string/join "," [1 2 3])

20:05 jimi_hendrix: zodiak, uhh

20:05 is there a difference?

20:05 sritchie, is there a :use option then?

20:05 sritchie: yeah

20:05 zodiak: jimi_hendrix: joke, kinda, I am learning clojure as well ;)

20:05 sritchie: you don't need that ' when you're inside the namespace macro, (ns ...), because macros don't evaluate their arguments

20:06 use and require are functions, so they need their arguments quoted, for this stuff

20:06 zodiak: I dare say that namespaces/requires/use is were most news trip up

20:06 s/news/newbs/

20:06 sexpbot: <zodiak> I dare say that namespaces/requires/use is were most newbs trip up

20:06 zodiak: sexplot +karma

20:07 good gods.. this autocorrect is annoying. what's a 'sexplot' ?

20:07 sritchie: (inc sexpbot)

20:07 sexpbot: ⟹ 0

20:08 gfrlog: (inc sexplot)

20:08 sexpbot: ⟹ 1

20:19 zakwilson: (dec sexplot)

20:19 sexpbot: ⟹ 0

20:19 zakwilson: (inc sexplot)

20:19 sexpbot: You want me to leave karma the same? Fine, I will.

20:19 zakwilson: Heh

20:25 sritchie: jimi_hendrix, if you're interested, here's some code for blackjack that I wrote in clojure: https://github.com/sritchie/blackjack/blob/develop/src/blackjack/core.clj

20:26 this has some uses, requires, and tests in a self-contained project that might be helpful to look at

20:27 jimi_hendrix: sritchie, cool, will check out

21:16 amalloy: summary of quoting: (let [x 1] (print x 'x)). here the symbol x has been given the local value of 1, which is the first thing printed. the quote on the second one prevents evaluation, printing the actual *symbol* x instead of its value

21:53 pcavs: what's the idiomatic clojure constant naming convention? ALLCAPS? CL *ALLCAPS* ?

21:56 TimMc: pcavs: Most things are constants, yeah?

21:56 Scriptor`: I'm not sure if constants are idiomatic in clojure

21:57 right, since most things are immutable anyways

21:57 TimMc: I think people tend to emphasize the things that *aren't*.

21:57 ^^^^^^^^

21:57 :-)

21:58 pcavs: I mean more along the lines of constant strings for various purposes or constant magic numbers

21:58 I'll just go with CL earmuffs

21:59 TimMc: pcavs: In Clojure, earmuffs are generally used for stuff that can be rebound.

21:59 hiredman: http://dev.clojure.org/display/design/Library+Coding+Standards

21:59 "Use *earmuffs* only for things intended for rebinding. Don't use a special notation for constants; everything is assumed a constant unless specified otherwise."

22:02 pcavs: well no earmuffs it is!

22:05 ViciousPlant: does earmuff has special meaning here

22:07 amalloy: ViciousPlant: *foo* looks like a foo wearing earmuffs

22:11 ViciousPlant: get it, thanks

22:42 pcavs: #findfn (fn [x] (< x 2)) [3 4 5] false

22:43 amalloy: $findfn (fn [x] (< x 2)) [3 4 5] false

22:43 sexpbot: [clojure.core/identical? clojure.core/isa? clojure.core/= clojure.core/contains? clojure.core/every?]

22:43 pcavs: amalloy: thanks

22:50 I just want some to return false, thoughts?

22:50 false instead of nil that is

22:50 without resorting to (not (nil?

22:51 amalloy: pcavs: suggestion: stop caring about the difference between false and nil except in rare cases

22:51 why do you think you need false?

22:51 pcavs: lemme check

22:51 ,(if nil "wtf" "ok")

22:51 clojurebot: "ok"

22:51 pcavs: guess I don't ;)

22:52 amalloy: pcavs: there are exactly two things that are treated as false in an (if) test: false and nil

22:52 pcavs: thought it was just false

22:52 amalloy: nah, that's java

22:53 pcavs: but I'm thinking of scheme I think, cause nil doesn't exist right?

22:53 amalloy: pretty sure scheme has nil

22:54 seancorfield: nice to be home and on a nice high speed network after spotty hotel wifi all weekend! :)

23:12 pcavs: amalloy: scheme does not have nil, it just has the empty list as annotated as (quote ())

23:12 a somewhat pedantic difference, but I forget the reasoning behind it...

23:21 amalloy: well, fair enough. that's what i get for learning CL instead of scheme

23:33 hiredman: clojure does not require the emtpy list to be quoted

23:33 ,(= () '())

23:33 clojurebot: true

23:34 pcavs: ,()

23:34 clojurebot: ()

23:34 pcavs: ,(= () nil)

23:34 clojurebot: false

23:36 amalloy: hiredman: based on my brief study just now, it looks like scheme didn't standardize on whether () has to be quoted?

23:37 hiredman: no idea, I would expect most schemers would prefer the regularity of it being quoted

23:51 ihodes: amalloy: i'm pretty sure you need to quote it

23:56 amalloy: ihodes: yeah, certainly that's the most portable. i ran across http://wiki.wordaligned.org/sicp/published/FrequentlyAskedQuestions, which suggests some impls don't make you

Logging service provided by n01se.net