#clojure log - Apr 29 2011

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

0:00 dnolen: choffstein: what I mean is what advantage over an atom?

0:00 choffstein: ...uh, no idea. As I said, I am very new to clojure :)

0:01 amalloy: i wonder if the popularity of refs, when atoms would do, is related to refs being an older language feature

0:01 (they are, right? i'm not imagining it?)

0:01 dnolen: choffstein: dosync is about coordinating changes between data, if you just need to serialize access to something, atoms are fine and much faster.

0:01 choffstein: amalloy: I use ref because I come from a SML background -- and ML has refs. Maybe that's it?

0:02 dnolen: ah, I see. atoms may be okay then :)

0:02 cemerick: amalloy: "I'm using _STM_, baby!" is enough of a thrill for a lot of people to motivate the usage. ;-)

0:02 amalloy: nice

0:03 carllerche: I'm trying to write a connection pool, would it be better to represent it as an atom -> { "hostname" PersistentQueue } or maybe ref -> { "hostname" ref -> PersistentQueue } and then use dosync, or maybe a ref -> { "hostname PersistentQueue } directly and still use dosync?

0:04 amalloy: i can't think of a good reason to have a ref of a map of refs

0:06 choffstein: dnolen: when you say coordinating changes between data, what exactly do you mean? In a concurrent sense -- like a database?

0:06 dnolen: choffstein: yes.

0:06 choffstein: dosync is like a db transaction

0:07 choffstein: dnolen: well, then it might make sense for my 'sessions' to be refs then, right, since those would be used across website users?

0:07 whereas something that is specific to an individual session that will only be touched by a user and is just being used for serialization can be an atom

0:07 ?

0:09 dnolen: choffstein: dosync if there are not two peices of data involved doesn't make sense, to me at least. dosync is about changing > 1 refs.

0:10 choffstein: Annnnddd that makes a whole lot more sense now.

0:10 carllerche: amalloy: well, if trying to modify the individual queues becomes highly contended, wouldn't that loosen up the number of transactions that need to be restarted?

0:10 choffstein: so if I had a list of refs and I wanted to alter them all, I would wrap it with a dosync?

0:11 carllerche: (i haven't actually gotten around to using refs yet, so I don't know)

0:11 dnolen: choffstein: yes, but you want to control the scope of a transaction, better for a transaction to try to change two rather than ten refs at the same time.

0:11 choffstein: hmmm. I think i'll leave transactions alone for a little while :D

0:11 I think i'm pretty happy with my horrible hacking for this evening.

0:12 amalloy: your use of the word "pooling" implies, to me, a fixed-size pool, so you never need to alter the top-level structure. it can just be an immutable map of (somethings) to (refs of connections)

0:12 dnolen: carllerche: I don't know much about efficient connection pools, I would look at how other people have done it. atoms and and refs have costs. but maybe efficiency is not a big concern in your case.

0:12 carllerche: amalloy: I'm actually building an HTTP reverse proxy that could have arbitrary end points

0:13 so, basically my goal is to determine the total number of open connections that can be held at once (in the thousands) and build an LRU that can manage that

0:13 amalloy: okay...

0:14 i'm hearing you say "yes, i have a fixed-size map"

0:14 choffstein: alright. time for bed before my brain melts. later all.

0:15 carllerche: amalloy: well, the keys can't be predetermined... it would be based on usage

0:15 aka, i can't preallocate the connections

0:17 i guess i could try the various options and see what works best

0:18 although, i wonder if i could just implement it as commutative operations

0:19 amalloy: so, what you are saying is that a ref to a map of refs is just crazy talk?

0:19 amalloy: yes. i have violent reactions to overuse of mutable state, so take that with a grain of salt though

0:20 rata convinced me an atom of a map of agents made sense, though, at some point

0:21 Apage43: do agents have any ordering guarantees?

0:22 cemerick: carllerche: I presume that any talk of refs in conjunction with IO stuffs is crazy. Transactions will be retried. IO operations should not be retried. :-)

0:22 amalloy: Apage43: all requests from thread X will be processed in the order X sent them

0:22 Apage43: k

0:22 i figured that'd be the case, just didn't remember

0:23 cemerick: the commutative part (if using commute) won't be though

0:24 carllerche: cemerick: right... this is just for some structure that can store / retrieve objects

0:24 no IO operations

0:37 i'm confused about commute, is it possible for the retval of commute to be different from the value the ref gets set to?

1:16 Apage43: carllerche is gone

1:16 but yes

1:17 or rather

1:18 well, it barely matters.

1:20 tomoj: I'm interested

2:58 stirfoo: does this profile macro look correct? http://paste.lisp.org/display/121658

2:59 the thing that bugs me is a given entry function shows less time than functions called by that entry function

3:01 clgv: stirfoo: the initial let looks fine. dont forget about lazy evaluation which can cause your functions to return fast since the real evaluation is postponed to the time the entry in the lazy seq is read

3:01 stirfoo: clgv: yes, that's something I haven't gotten a grip on yet, lazyness

3:02 clgv: your if-let has a different meaning than you might think

3:02 stirfoo: oh? do tell

3:04 clgv: that might work as well: ##(if-let [[a b] [nil nil]] [a b] 'else)

3:04 but it seems that doesnt matter in the remaining code

3:04 sexpbot: ⟹ [nil nil]

3:05 clgv: summarizing: the code looks ok

3:08 stirfoo: ok, thanks clgv. Is the actual book 'joy of clojure' available yet? I know I can get a pdf. Haven't checked their site in a while.

3:08 clgv: stirfoo: yes it is

3:09 stirfoo: awesome

3:09 clgv: even on amazon now ;)

3:10 ambrosebs: mine just came in the mail

3:10 love the guy on the cover

3:11 stirfoo: I read one or two of the freebee chapters a while back. Seemed like a well written book.

3:11 ambrosebs: I ordered "Learn you a haskell for great good", which has a blue elephant on the front... two fun covers with fun titles :)

3:12 stirfoo: Did Duane draw the elephant? (scheme joke)

3:14 ambrosebs: *whoosh* :P

3:16 on the way to work this morning I was thinking if "The Joy of Java" would pop up in some form xD

3:17 the only cover I've seen that advocates java as "fun" is the Pragmatic Programmers' Stripes book

3:17 subtitled: "...and Java web development is fun again!"

3:17 I laughed

3:17 still, good book, good framework.

3:30 amalloy: tomoj: (commute) sets the ref to some temporary value for within your transaction, and returns that value. when you go to commit your transaction, if anyone else has altered/commuted that ref in the meantime, the stm re-performs the commute function with the new ref value and commits that

3:30 it doesn't have to retry the transaction or tell you about the new value at all, because you told it commuting was okay

3:31 so it is possible for (commute) to return a value that the ref never actually has, outside of your snapshot fantasy-land

4:02 clgv: Is it possible to combine two different plots with different scales in on Incanter chart? e.g. one scale on the left the other on the right?

4:03 *one

4:21 pyr: hi

4:23 I'm facing a weird use case with leiningen. How do I integrate jars which are not in any maven repo ?

4:28 I could put them in lib/ but every lein clean flushes them out

4:29 clgv: pyr: just add ":disable-implicit-clean true" to your project.clj

4:30 pyr: 'k thanks

7:11 ordnungswidrig1: *print-dup* causes records to be dumped as #=foo.BarRecord/create {:a 1 :b 2 :c 3} how to I dump records so that load-string will read them?

7:43 thorwil: ordnungswidrig: isn't read meant to used for such dumps?

7:44 ordnungswidrig: thorwil: the reader doesn't support record literals yet

7:44 thorwil: the need of importing the record class makes is worse

8:09 clgv: ordnungswidrig: you could dump them as normal maps and read those maps and assoc them...

8:09 ordnungswidrig: clgv: no so easy because you need some reflection to initialize an empty record.

8:09 clgv: but certainly possible

8:11 clgv: ordnungswidrig: oh ok. I assumed you will know the record type at the time you want to read it

8:13 ordnungswidrig: clgv: no, but I can flip it into a map, like (defrecord Foo [a b c]) and (Foo. 1 2 3) -> {::type "some-ns/Foo" :a 1 :b 2 :c 3 }

8:14 clgv: on read time i can transform back

8:14 clgv: ordnungswidrig: I know ;) but it's less code without the reflection part and thus easier ;)

8:16 ordnungswidrig: humm why not write (Foo. 1 2 3) to file? maybe with namespace associated?

8:30 fliebel: dnolen: I'm in the train, read the little paper. The syntax is indeed weird. What of this all is most relevant to your plan?

8:30 dnolen: the pattern matching paper?

8:30 fliebel: ^

8:32 fliebel: yea

8:32 uhm, no, well... the one with ml

8:34 dnolen: fliebel: yeah that's the pattern matching paper. the paper shows you how to do pattern matching efficiently, the implementation allows you to break apart the compilation and analysis/optimization steps.

8:35 which makes the implementation a lot simpler/cleaner than previous papers on papers on pattern matching.

8:35 david`: what's the difference between (case x) and (condp = x)?

8:36 dnolen: david`: case does not test possibilities.

8:36 fliebel: dnolen: Ah, I see. And you want to use Logos to generate the maximum sharing shallow stuff?

8:37 david`: I see, so the "= x" can be changed to really any test condition

8:38 like condp some [1 2 3 4]

8:38 dnolen: fliebel: no I plan on implementing what's described in the pattern matching paper as is. but pattern matching has a problem. It's closed, you can't add stuff later. Also order matters, it's easy to make a mistake and write broken pattern.

8:39 fliebel: keeping things open is unrelated to the logic engine, however automatically reordering clauses is something the logic engine can do.

8:40 fliebel: consider (defm foo [x] :guard (even? x))

8:40 fliebel: then consider that someone else wants to add (defm foo [0]) after the fact.

8:40 fliebel: because the first one was defined first, the second one will never be reached.

8:41 fliebel: we can fix that with a logic engine.

8:41 fliebel: oh, so you are just implementing these pares really. I thought you want to tell logos the properties of the tree ansd say "go do it"

8:43 dnolen: fliebel: it will store properties of the tree, but it's there to solve implication issues like the one above.

8:43 fliebel: oh, okay. Interestng. I need to go now though, my train isn't going where it should.

8:48 dnolen: david`: yes.

8:55 david`: kewl

10:12 devn: dnolen: intensely awesome work

10:12 clgv: (apply third-party-macro param1 param2 options) does not work. can I work around that somehow?

10:13 dnolen: devn: heh, at this point we're still in the realm of ideas ;)

10:14 devn: dnolen: even still, the germ of the idea is exciting

10:14 dnolen: is there video anywhere of this LispNYC talk you gave?

10:15 apgwoz: devn: you have to move to nyc to see it

10:15 sorry, them's the rules

10:15 devn: apgwoz: how big is your apartment?

10:15 apgwoz: big enough for my wife, a baby (soon) and myself. not for you

10:15 :)

10:15 devn: alls i've got is this here stick and bindle

10:16 apgwoz: edw: chicken scheme can speak to slime now

10:18 devn: apgwoz: you bring up an important point. i'd like a move sometime soon.

10:18 apgwoz: madison isn't happening enough for you?

10:18 Ramblurr: do most people use the stable clojure release or use the live git version?

10:18 apgwoz: devn: meetup is hiring, though there's only a tiny tiny tiny bit of clojure code at the moment.

10:18 devn: I really like Madison, but once my girlfriend is finished with school next semester we're sort of planning on a move East or West

10:19 apgwoz: yeah, i visited madison last september, nice place.

10:20 devn: there's going to be a madison ruby conference this year -- excuse for you to make a visit

10:21 apgwoz: either way, maybe ill come out to NYC for a weekend and see some friends, drop by the LispNYC meetup

10:21 Ramblurr: depends on what you want to do

10:22 Ramblurr: id say most are on stable, though

10:24 apgwoz: devn: but i don't really like ruby, so that's a reason to avoid madison :)

10:26 Ramblurr: devn: ah, hm. I asked because my 1.2.0 jar seems to be missing functions: join, blank?

10:27 devn: Ramblurr: what's your setup?

10:27 Ramblurr: devn: oh, i have to "use" the string module heh

10:28 clgv: how can I avoid this: (eval `(xy-plot ~x ~first-col ~@options)) ???

10:28 xy-plot is a macro unfortunately sothat I can't use apply

10:28 Ramblurr: devn: is this error expected when doing (use 'clojure.string) ? WARNING: replace already refers to: #'clojure.core/replace in namespace: user, being replaced by: #'clojure.string/replace

10:29 devn: Ramblurr: yes.

10:29 Ramblurr: are you just getting used to the idea of clojure's namespaces and such?

10:29 Ramblurr: http://blog.8thlight.com/articles/2010/12/6/clojure-libs-and-namespaces-require-use-import-and-ns

10:29 pjstadig: clgv: write your own wrapper macro?

10:29 Ramblurr: devn: yea, this is my first encounter with them

10:30 devn: thanks for the reading

10:30 devn: Ramblurr: not a problem. have fun

10:30 clgv: pjstadig: errmmm... how?

10:30 just extract the code over there?

10:31 pjstadig: yeah something like (defmacro xy-plot2 [x first-col & options] `(xy-plot ~x ~first-col ~@options))

10:32 eval + syntax-quote is essentially macro evaluation anyway

10:35 clgv: pjstadig: hmm I can't really get around it. I want to write a function but the option-handling forces me to write a macro if I do not use eval + syntay-quote

10:35 pjstadig: where is xy-plot from and why is it a macro?

10:37 clgv: it's from Incanter

10:37 I dont know why it is a macro

10:37 it just seems to do some default value handling for options

10:38 sritchie: here's the source -- https://github.com/liebke/incanter/blob/8736bc3cae44491172031b381c6e165c0bd1139c/modules/incanter-charts/src/incanter/charts.clj#L984

10:38 clgv: sritchie: already looking at it ;)

10:39 sritchie: clgv: just trying to live up to clojurebot's helpfulness :)

10:40 Ramblurr: o_0 I'm getting different results from a function when i call it with dotrace or by itself

10:43 chouser: Ramblurr: is dotrace printing return values of functions or their arguments? or just listing the names of functions being called?

10:44 Ramblurr: chouser: both

10:44 chouser: preparing a snippet, one sec

10:44 pjstadig: clgv: you could do something icky like (apply xy-plot* x first-col @#'incanter.charts/create-xy-plot options)

10:45 chouser: Ramblurr: if it prints return values or args, it may be forcing lazy sequences that wouldn't otherwise be realized.

10:46 Ramblurr: chouser: oh, i see

10:46 clgv: pjstadig: hmmm I guess I'll write the whole thing as macro

10:48 Ramblurr: chouser: http://pastebin.com/aALcDt1y

10:51 chouser: and here is the output different http://pastebin.com/QXvHVige Would you say this is a case of lazy seqs being evaled?

10:59 pyr: hi, do you any use cases where clojure.contrib.sql's with-query-results could yield an exception because distinct? was called with no arguments

11:15 mec: (let [[a b c] (if t [1 2 3] [2 3 4])] ...) vs (let [foo (fn [a b c])] (if t (foo 1 2 3) (foo 2 3 4))

11:20 semperos: is there any reason to use clojure.string/escape over clojure.string/replace?

11:20 kzar: I'm trying to get my head around Enlive, I've made a snippet to add stylesheet links to my page's layout. For my snippet selector I've used [:link {:rel "stylesheet"}], I've then done used set-attr on [:link] in an attempt to set the href of the stylesheet. I can't get it working though. Also it seems weird that I have to define my template to point to layout.html and then point my css including snippet at the layout

11:20 .html template too. I get the feeling I've totally misunderstood something here?

11:20 semperos: in microbenchmark, clojure.string/replace performed better

11:21 other than the need to replace more than one thing in a single swipe

11:26 manutter: kzar: do you have a gist?

11:26 kzar: manutter: http://paste.lisp.org/display/121664

11:27 manutter: The css-include part is what's confusing me although it's likely all backwards

11:42 edw: In theory, shouldn't re-factoring conserve the does-it-work? property?

11:54 kzar: manutter: I've cracked a couple of problems, just got to figure out how to get it populating the href properly now

12:07 ah I've cracked it :)

12:14 manutter: Man, bosses can be so demanding at times :\

12:14 Good, I'm glad you got it, I got called away

12:15 kzar: no worries! I know what that's like heh

12:22 TimMc: edw: Yeah, and as long as it doesn't affect your API, your automated tests should all still pass.

12:55 (You *are* writing tests, yes? :-P)

12:55 semperos: anyone know proper spec for clojure.contrib.sql for a DATETIME column? tried :datetime

12:56 sorry, for the clojure.contrib.sql/create-table fn

13:11 ataggart: stuarthalloway: free to discuss the bit-ops stuff?

13:12 stuarthalloway: yep

13:13 ataggart: read your responses, everything looks as I expected. ONe question: what's the point of having Object overloads if everything gets treated as a long anyway?

13:14 stuarthalloway: I think you will find that there are code paths where things come in as objects

13:14 you can try long only and see what happens :-)

13:14 ataggart: I have: https://github.com/ataggart/clojure/commits/bit-ops

13:14 the compiler knows how to push numbers to long primitives

13:16 if that commit looks good, I'll make a patch and attach it to 767

13:17 stuarthalloway: the core.clj changes in that commit seem related to something else ?

13:17 reviewing the numbers.java changes now

13:18 ataggart: the change in core.clj is because where the exception on passing a double to even? went away

13:20 stuarthalloway: seems like exception is the right behavior

13:20 ataggart: it used to be thrown via bitAnn on line 1201 in Numbers

13:20 stuarthalloway: what does it mean for a double to be even?

13:21 ataggart: yep, it's always thrown an exception on non-integer nums

13:21 just changed the location

13:21 stuarthalloway: let's leave that out of the patch

13:22 do you know if the shiftLeftInt variants are ever used anywhere?

13:22 ataggart: they are not

13:23 I'm not clear on what you want left out of the patch. even? is supposed to throw an exception; that exception used to be thrown by bitAnd which used to throw it in bitOps, bit bitOps is gone, so someone needs to throw the exception when even? is called with a non-integer

13:24 stuarthalloway: what happens without the change in core?

13:24 ataggart: tests failed, don't recall what

13:24 lemme see

13:25 stuarthalloway: thanks, trying it here as well

13:25 did you see that #426 (case) finally got in?

13:26 ataggart: I'm not a religious man, but....

13:26 what was the voodoo you used to find those bad numbers?

13:27 stuarthalloway: ataggart: I thought Alan told you

13:28 https://github.com/clojure/test.generative

13:28 ataggart: he mentioned you had some framework, ah yeah nice

13:28 stuarthalloway: the tests are still in there (under examples)

13:28 aredington: Alan was probably avoiding stealing Stu's thunder on dropping that bombshell

13:32 ataggart: sigh, the compiler is automatically casting from non-integers to long

13:32 * ataggart wishes someone would apply CLJ445

13:32 aredington: What kind of non-integers ?

13:32 ataggart: ratios, doubles

13:33 anythign that's not a long or int

13:34 when the param is long, but the arg is neither long nor int, the param gets treated as an object and then automatically cast to the param type

13:35 I can manually deal with all the type checking, but... ugh

13:36 stuarthalloway: not sure I am totally following you without seeing it run -- going to build it now

13:36 sorry slow -- I am multitasking several numerics tasks here

13:36 ataggart: ya sry, I can see it since my head has been in the compiler for a few months now

13:37 anyway, it's a problem with bit-ops really, since (bit-and 1.5 1) is coming back 1

13:37 because that 1.5 is getting truncated to a long

13:38 by the compiler

13:38 don't waste your time on it, lemme fix that

13:38 stuarthalloway: so would the Object/long and long/Object variants fix that?

13:40 ataggart: they wouldn't, but for (bit-and double long) the compiler would choose and(Object, long) and we can perform manual type checking, which is what bitOps used to do

13:40 it's a deficiency in the compiler

13:40 imo

13:40 stuarthalloway: fair enough, but let's get this done

13:40 ataggart: yup, half way there

13:52 dakrone: stuarthalloway: response to your email, I need a float for a test as such: (is (= "3.14" (json/generate-string (float 3.14)))), but fails with the 1.3 stuff

13:52 for testing a lib that has float methods

13:53 stuarthalloway: dakrone: where is the float method?

13:54 called inside json/generate-string somewhere?

13:54 dakrone: inside the generater, in a condp looking something like "... Float (.writeNumber jg ^Float obj)"

13:54 yes

13:55 stuarthalloway: and you need float fidelity, so double promotion would be a bug?

13:56 ataggart: *cough*445 fixes that*cough*

13:56 dakrone: yes, otherwise I get the error that it can't find a correct method

13:57 stuarthalloway: let me see if I have the general issue right: you have a serialization framework that depends on access to the different Java primitive types in order to drive different semantics

13:58 dakrone: stuarthalloway: http://jackson.codehaus.org/1.7.4/javadoc/org/codehaus/jackson/JsonGenerator.html#writeNumber(int) there are 7 .writeNumber methods, which can be treated differently internally depending on class

13:59 I have no way to guarentee that .writeNumber(double) behaves the same as .writeNumber(float)

13:59 stuarthalloway: dakrone: so you could get there by calling them directly (with float hinting) but any indirection (e.g. a Clojure fn) makes things doubles

13:59 * stuarthalloway thinking

14:00 rhickey: dakrone: calling such an overloaded thing requires coercions

14:00 coercions are not hints

14:01 stuarthalloway: rhickey: how does that work when there is a Clojure fn call between the float the Java method to be called

14:01 dakrone: rhickey: If I'm doing condp with dispatch on type though, by that point the compiler's already made it a double

14:01 rhickey: stuarthalloway: like what?

14:02 dakrone: condp doesn't do type dispatch on primitives

14:02 semperos: sorry to re-ask, had to leave an hour ago

14:02 rhickey: if you want a boxed Float make one

14:02 semperos: does anyone know how to use clojure.contrib.sql/create-table with datetime columns?

14:02 rhickey: (float x) does not make a Float

14:03 dakrone: no, understandable, how should I dispatch in a function then on primative, and call it from a test if in the test I use (float 3.14) and by the time it reaches a dispatch it's a double?

14:04 stuarthalloway: dakrone: (Float. 3.14)

14:04 rhickey: stuarthalloway: you can't route floats around, Clojure doesn't have primitive floats

14:04 ataggart: it *could*...

14:04 stuarthalloway: dakrone: when you are making a fn call you are using objects anyway

14:04 rhickey: (float x) produces a float for immediate consumption by a Java thing that takes a float

14:04 stuarthalloway: ataggart: go finish that patch :-)

14:05 ataggart: aye sir

14:05 dakrone: okay, then I will not be able to handle doing json enconding of java methods that *could* return floats

14:05 stuarthalloway: dakrone: yes, you could, with (Float. )

14:05 rhickey: dakrone: I don't see why not

14:05 dakrone: (json/encode (.methodThatReturnsAPrimativeFloat foo)), at that point it would be a float, how can I dispatch on it?

14:06 rhickey: ataggart: no, it won't

14:06 ataggart: stuarthalloway: https://github.com/ataggart/clojure/commit/496135716ab8687ba4373ca9799db57ed6638060

14:06 hiredman: if you call a java method and it returns X, but you aren't sure what type X is, how do you determine the type of X in such a way that avoids boxing X as a different type?

14:06 dakrone: I can dispatch in encode in a condp with Float, but it's not a Float and I need to dispatch in encode on what type it is

14:07 pjstadig: right, it's not *inter*op if it only goes one way, if values returned from java are converted to doubles, then there's no way to maintain fidelity of floats to/from java

14:07 ataggart: rhickey: every fall to a float-taking method is effectively called like Foo.bar((float)(double)myFloat). That causes unexpected changes in value, and can be easily fixed.

14:07 rhickey: dakrone: how would you write json/encode in java?

14:09 hiredman: dakrone: you happen to have it also written up in java, yes?

14:09 stuarthalloway: ataggart: given no plan to support big ints, can we not replace bitOpsCast with a simple cast to long?

14:09 rhickey: call RT.box then

14:10 hiredman: rhickey: on which side of the fn call?

14:10 ataggart: stuarthalloway: the choices are unchecked cast to long, checked cast to long which accepts all numic categories (i.e. RT.longCast(Object)), or the category-specific checked cast I added.

14:11 hiredman: calling RT/box inside the fn is too late (conversions have happened) calling it outside means all callers of encode have to call (encode (RT/box x))

14:11 dakrone: rhickey: In java the point would be moot since there would no longer be a wrapper in the middle, you would call the generate method directly and java would route to the right place

14:11 kzar: Does anyone else find that sometimes emacs stops displaying function arguments in the mini buffer after a while?

14:11 rhickey: hiredman: was speaking to json/encode

14:12 hiredman: uh, I thought I was too?

14:12 rhickey: I'm not particularly attached to floats as Doubles if itsa big problem for people. short/int/long as Long is a bigger deal

14:13 semperos: kzar: you using slime/swank?

14:13 hiredman: given the lack of floating point weirdness I can't imagine it would be a big deal

14:13 kzar: semperos: Yea, it works fine but just sometimes after a while it breaks

14:13 rhickey: dakrone: I don't understand

14:14 kzar: semperos: It's probably my god-awful code causing it to seppuku heh

14:14 no_mind: I have serialzed a map and stored in a string to dump in a db. NowI want to deserialize the sw do I do it ? map. Hotring to

14:14 semperos: kzar: I've had similar happen; sometimes I forget to compile and load ns's

14:14 sometimes it just needs a classic reboot :)

14:15 raek: no_mind: are you talking about pr-str and read-string?

14:16 dakrone: rhickey: In java, I'd encode directly and be happy, no special forms or rewriting required. In clojure, I need to dispatch on things like vectors, lists, maps and such to translate them to an encodeable-format before passing them down to the java methods, once I have a list though, I need to dispatch on each element in the list, with could be a Number, so I do a condp and dispatch on Number. I do this recursively, so have a co

14:16 does that kinda explain it?

14:16 no_mind: raek: dont know what they are ? I serialized the string with *print-dup*

14:17 stuarthalloway: rhickey: should (bit-and 1N 1) throw an exception, or coerce to primitive long and proceed?

14:17 raek: ,(let [m {:a "1", :b "2"}] [m (pr-str m) (read-string (pr-str m))])

14:17 clojurebot: [{:a "1", :b "2"} "{:a \"1\", :b \"2\"}" {:a "1", :b "2"}]

14:18 amalloy: dakrone: fyi your huge-long message was too long for irc and got truncated at "have a co"

14:19 pjstadig: upcasting bytes, shorts, ints as longs makes sense, because those types are precise and you can just chop off some data to down cast it without any loss

14:19 rhickey: stuarthalloway: if bit-and is defined for longs only then that has the same answer as should any long-taking method accept BigInts (i.e. the converson question we talked about this morning)

14:19 pjstadig: as we've seen upcasting from float to double produces slightly different values

14:19 raek: no_mind: if a value is built only of strings, keywords, symbols, lists, vectors, maps etc (i.e. only object that are part of the clojure syntax), then you can use pr-str to turn it into a string and use read-string for the reverse

14:19 pjstadig: floats are not exactly a subset of doubles

14:20 no_mind: ok

14:20 dakrone: rhickey: http://p.writequit.org/explain.html

14:20 amalloy: thanks for the heads up

14:20 stuarthalloway: rhickey: what about even?, which (as implementation detail IMO) is implemented with bitops

14:20 rhickey: dakrone: that's getting bigger and bigger - make the problem smaller - what would the signature of encode be in Java?

14:22 dakrone: rhickey: that's what I'm saying, there would be no need for encode in java

14:22 It's entirely possible that I am Doing It Wrong (tm)

14:22 will look and get back to you

14:23 rhickey: stuarthalloway: what about it?

14:24 stuarthalloway: should even? work for bigints? - of course

14:25 stuarthalloway: rhickey: right on, so the implementation has to change, since bit-and will not work for big ints

14:25 rhickey: stuarthalloway: sounds right

14:28 stuarthalloway: totally separate issue: running Clojure in IDEA for debugging

14:28 scgilardi: would the change be to use BigInteger's "and" method directly? avoiding a division or div/rem operation for even? would be nice.

14:29 stuarthalloway: I am stuck because the basic compilation doesn't put the version resource in the right place, causing an NPE reading the version string

14:29 aredington: (= (mod <num> 2) 0) should work transparently across all integer values

14:29 stuarthalloway: I can think of a dozen workarounds or fixes, any strong opinions? Or does anybody have a workflow (not including ant or maven) for interactive debugging?

14:30 hiredman: I have a lein'ized clojure build

14:30 fogus`: stuarthalloway: sed was my Huckleberry. It sucked

14:31 scgilardi: aredington: mod is division-y

14:31 hiredman: I rember futzing with the version file issue

14:31 stuarthalloway: fogus` : why is there a backtick in your name?

14:31 hiredman: dunno how well it would work in IDEA

14:31 fogus`: stuarthalloway: Some other fogus took my name

14:31 aredington: too many fogii

14:31 stuarthalloway: fogus` : poor Optimus had the same problem

14:31 aredington: that's right you can't outtype me

14:32 redinger: fogi?

14:32 fogus`: fogen

14:32 optimus`: not funny guys

14:33 hiredman: https://github.com/hiredman/clojure/commit/0a1c064c767991004b94aa796181aed111c98f34

14:34 stuarthalloway: hiredman: zoinks

14:35 hiredman: oh, actually now I remember it doesn't build with a stock lein either

14:35 damn

14:35 lein puts ./src on the classpath which breaks for building clojure

14:36 bulters: alandipert: I was just wondering who would be optimus prime then.

14:36 mec: anyone know the O of adding to a sorted set?

14:37 chouser: mec: there's a nice chart for that...

14:37 stuarthalloway: ataggart: re http://dev.clojure.org/jira/browse/CLJ-781, you need to put your shorts in the first branch of the if

14:38 bulters: mec: ordered? then it\s usually a O(log n/log r) op

14:38 stuarthalloway: ataggart: otherwise they fall through and get converted to doubles, then longs.

14:39 ataggart: stuarthalloway: what are you referring to?

14:39 the patch on 781?

14:39 amalloy: mec: log2(n)

14:39 mec: thanks all

14:39 stuarthalloway: ataggart, sorry, wrong link: http://dev.clojure.org/jira/browse/CLJ-782

14:40 shorts used to fall down to the longCast at the bottom

14:40 fbru02: stuarthalloway: Hey ! Can you please take a look at http://dev.clojure.org/jira/browse/CLJ-730 ?

14:41 stuarthalloway: fbur02: we'll take a look, but lower priority than bugs

14:42 ataggart: if you are working on the bit-ops patch, I can tweak 782 and submit it to Rich

14:43 rhickey: https://github.com/clojure/clojure/commit/6fb09f402c5448070a2efc64ebd64285480b263f

14:43 ataggart: ok, just add Short and Byte to the first if

14:43 * fogus` can verify that Clojure does indeed have a 2-pass compiler.

14:44 stuarthalloway: rhickey: performance tweaking question for you

14:44 rhickey: stuarthalloway: ok

14:44 stuarthalloway: ataggart's patch http://dev.clojure.org/jira/browse/CLJ-782 correctly splits out a new path in longCast

14:44 hiredman: the passes are Parser/paser and Expr/(emit|eval)?

14:44 parse

14:45 stuarthalloway: but that split implies the need to also split out short and byte, which used to fall to the bottom

14:45 is it important that those conditionals be away from the top, so the hot path (int and long) at the top doesn't pick up two more checks?

14:45 or does the short/byte case need to be handled further down

14:46 rhickey: stuarthalloway: can't read these damn context-less patches

14:46 stuarthalloway: but yes, prioritize long and int please

14:47 fbru02: stuarthalloway: thanks :)

14:47 stuarthalloway: rhickey: apply the patch locally and then view in IDEA :-)

14:47 rhickey: stuarthalloway: applying patches in order to see what they do is a huge time suck

14:47 ataggart: stuarthalloway: posted link to updated bit-ops commit for your review

14:48 stuarthalloway: ataggart: can you move the short/byte check out of the first if, down later in the fn? (see discussion with rhickey above)

14:48 ataggart: stand by

14:52 and updated cast fix: https://github.com/ataggart/clojure/commit/59bc3b2010ae7b0c8efb77e82939118b2f435045

14:54 stuarthalloway: ataggart: https://github.com/ataggart/clojure/commit/59bc3b2010ae7b0c8efb77e82939118b2f435045 looks good. please put the patch on the ticket and I will screen it

14:55 ataggart: still looking at the bit-ops patch and wondering how best to implement even?

14:55 aredington: checking even let's BigIntegers in the door which are then going to be cast to long for bit-and

14:56 ataggart: that shouldn't affect the eveness

14:56 the LSB is still going to be 1 or 0 irrespective of the truncation

14:57 stuarthalloway: ataggart: so we should need unchecked-long instead of long?

14:57 ataggart: yup

14:57 stand by

14:57 scottj: is there a shorter version of &&(reduce #(update-in %1 [%2] (fnil inc 0)) {} [1 2 3 1 2 1])

14:58 amalloy: scottj: ##, not &&

14:58 scottj: ##(reduce #(update-in %1 [%2] (fnil inc 0)) {} [1 2 3 1 2 1])

14:58 sexpbot: ⟹ {3 1, 2 2, 1 3}

14:58 amalloy: &(frequencies [1 2 3 1 2 1])

14:58 sexpbot: ⟹ {1 3, 2 2, 3 1}

14:58 dakrone: rhickey: I was able to work around the primative problem, I was indeed doing it not-wrong-but-not-the-best-way

14:58 thanks for the help

14:58 scottj: amalloy: thanks

14:59 amalloy: unless you're looking for a better way to reimplement frequencies

14:59 rhickey: dakrone: I wasn't much help, but glad you are unstuck :)

15:00 amalloy: scottj: i think your original question is how i solved http://4clojure.com/problem/55

15:09 choffstein: Hey all! I have a question: I am basically trying to perform a map, but also while using an accumulator. So its sort of like reductions, but I don't want the accumulator recorded. Is this idea possible? I think it can be done using a recursive solution, but I was wondering if it was a built in idiom

15:09 opqdonut_: :t mapAccumL

15:10 oh, sorry, I thought I was in #haskell

15:10 no, I don

15:10 't think I've seen a function for that in the standard library

15:10 but you might get a nice solution with map + reduce

15:12 choffstein: yeah, I didn't think there would be

15:13 opqdonut_: IMO reducing with a slightly intricate function is better than a custom recursive solution

15:13 choffstein: well, what I need to do is basically keep "track" of a previous label and carry that label through to all nil labels until i hit a new label

15:14 opqdonut_: that

15:14 bulters: I have a dependency in a leiningen project (in this case org.clojars.liebke/congomongo "1.0.0") and I try to 'use' it in a slime session I get a compile error (FileNotFoundException)

15:14 opqdonut_: certainly sounds doable

15:14 bulters: but checking the classpath, congomongo-1.0.0 is on it.

15:14 opqdonut_: (how come I keep hitting my return key by accident all the time?)

15:14 stuarthalloway: rhickey, ataggart: http://dev.clojure.org/jira/browse/CLJ-782 is screened

15:15 amalloy: choffstein: so use reductions, with a two-part accumulator: [the-map-value current-label]

15:15 bulters: any ideas what I'm doing wrong?

15:15 amalloy: then you can (map first (reductions (fn [[_ label]] (...return a vector of [map-value new-label]...))))

15:16 ataggart: rhickey has left the channel

15:16 amalloy: sorry, should be (fn [[_ label] current-input] ...)

15:17 choffstein: amalloy: that's what I was going to do, I just didn't know if that was idiomatic clojure

15:18 amalloy: choffstein: i tend to overuse the HOFs for cases when writing a lazy-seq by hand would be clearer and/or easier. this might be such a case

15:19 raek: bulters: did you check the classpath from within the clojure instance that could not use it?

15:19 choffstein: HOFs?

15:19 opqdonut_: higher order functions

15:19 like map, reduce

15:19 bulters: raek: yup, it clearly lists lib/congomongo-1.0.0.jar

15:20 raek: what namespace are you trying to use?

15:21 bulters: raek: tried 'everything' congomongo, liebke.congomongo, org.clojars.liebke/congomongo

15:21 TimMc: clojurebot: HOFs are higher order functions

15:21 clojurebot: anonymous functions are functions with no names

15:21 TimMc: bah

15:21 This bot can't conjugate.

15:22 raek: bulters: I don't think org.clojars.liebke is the official fork

15:22 Ramblurr: i'm having an issue where the results of dotrace are different than when i println the function's results :\

15:23 raek: bulters: in the jar, there's a namespace called somnium.congomongo

15:23 bulters: raek: trying somnium now

15:23 Ramblurr: unfortunately the dotrace result is the correct one

15:23 raek: bulters: docs semes to be here: https://github.com/somnium/congomongo

15:25 bulters: but for some reason, there isn't any stable (non-snapshot) version available

15:25 bulters: raek: my biggest hurdle I have so far in using clojure ;-)

15:27 raek: bulters: [congomongo "0.1.4-SNAPSHOT"] should work, but leiningen won't allow you to make a stable version of your project that depends on a snapshot version of a lib

15:27 this is probably why liebke pushed a private version

15:29 bulters: raek: Luckily I'm not releasing anything for the next few years

15:29 ;-)

15:29 thanks, it compiles :D

15:49 mec: how come some places in core.clj call (drop 1 ...) instead of just next?

15:50 rak85: hi, guys

15:50 a ! in the end of a function name is some kind of convention?

15:51 TimMc: rak85: Yeah, it usually indicates mutation.

15:51 Specifically, things that aren't safe to call in a transaction.

15:51 bulters: TimMc: So stuff that has side effects go to a x! function?

15:52 TimMc: bulters: I think ! is usually used to make it clear when it wouldn't otherwise be obvious.

15:52 bulters: ok, so store-blah is fairly obvious :P

15:52 TimMc: bulters: compare assoc vs. assoc! for instance

15:53 bulters: same as in ruby, one variant that is non 'destructive' and one that is.

15:53 mec: looks like its mainly for things that muck with atoms and transients

15:53 and vars

15:56 rak85: thanks everyone

15:58 dnolen: bulters: not quite, assoc! can only be used transients, and even then those can't be bashed in place.

16:01 bulters: dnolen: I have no idea what transients are... yet; guess it's google time

16:09 mattmitchell: i have what i think is a byte array: #<byte[] [B@ff22be7>

16:09 how do a pull out the items in that object?

16:09 is the duck streams contrib required?

16:09 ataggart: ,(aget (byte-array 1) 0)

16:09 clojurebot: 0

16:10 dnolen: ,(nth (byte-array 1) 0)

16:10 clojurebot: 0

16:10 ataggart: nth uses a seq though

16:10 iirc

16:11 mattmitchell: ataggart: thanks! trying that out now...

16:12 dnolen: ataggart: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L746

16:12 ataggart: yeah, so not a seq, but still more involved than aget

16:13 dnolen: ataggart: true

16:14 raek: ,(into-array [1 2 3])

16:14 clojurebot: #<Integer[] [Ljava.lang.Integer;@e8873a>

16:14 raek: ,(seq (into-array [1 2 3]))

16:14 clojurebot: (1 2 3)

16:14 mattmitchell: ok, so i could turn the byte array into a seq

16:14 dnolen: mattmitchell: if you don't care that you lose random access.

16:15 raek: mattmitchell: function that operate on sequences will call seq on the argument, so in most cases you can ommit seq

16:15 ,(map inc (into-array [1 2 3]))

16:15 clojurebot: (2 3 4)

16:15 mattmitchell: raek: ok cool

16:15 ataggart: (map inc (byte-array 3))

16:15 ,map inc (byte-array 3))

16:15 clojurebot: #<core$map clojure.core$map@b36022>

16:15 ataggart: bah

16:15 ,(map inc (byte-array 3))

16:15 clojurebot: (1 1 1)

16:16 ataggart: this is annying though: ##(type (aget (int-array 1) 0))

16:16 sexpbot: ⟹ java.lang.Integer

16:17 ataggart: wait what

16:17 ah 1.3.0 has that as a Long

16:20 kzar: This has a very real danger of being a bad idea, badly executed but can anyone spot what's wrong with this macro? http://paste.lisp.org/display/121675

16:21 raek: yup. all integer numbers are represented as Longs when they are boxed in 1.3

16:21 kzar: (I wanted it to just return nil on any exception.)

16:23 raek: kzar: you need to use gensym'ed symbols to bind values: (catch Throwable e# ...)

16:24 otherwise it will be resolved, as if it was meant to refer to a global var

16:24 ,`foo

16:24 clojurebot: sandbox/foo

16:24 raek: ,`foo#

16:24 clojurebot: foo__1290__auto__

16:24 raek: this is to avoid symbol capture

16:25 kzar: raek: So with # it's gensymed and then the variable ends up being bound inside the place where it's actually being used. Otherwise it's not gensymed and it ends up being global to the namespace, or at least it tries to be but because it's not present I (ironically) get an exception

16:26 ordnungswidrig: I'm looking for a way to serialize / dump a clojure value which consists of maps, list etc. but also refs, e.g. {:foo-by-id {1 (ref {:name "foo-1"}) 2 (ref {:name "foo-2"})}

16:27 print-dup does not support refs :-(

16:27 raek: kzar: let (and also catch) simply requires the symbol to not have a namespace part (and refuses compilation if the rule is not followed)

16:28 syntax-quote (`) simply adds namespace parts to all symbols (except for those representing special forms)

16:29 kzar: raek: Ah right I get you now

16:29 raek: Thanks :)

16:29 raek: but it won't add a namespace part if the symbol ends in #, instead it makes up a new unique symbol to avoid name collisions

16:37 amalloy: clojurebot: HOFs |are| higher order functions

16:37 clojurebot: Alles klar

16:37 amalloy: TimMc: ^

16:39 fliebel: dnolen: Sorry for leaving so abruptly earlier today. I've only just reached home :P Some crane drove through the catenary of the train I was supposed to take.

16:39 dnolen: fliebel: np.

16:41 fliebel: dnolen: That paper, it does not describe the actual pattern matching, does it? Just the underlying tree stuff.

16:42 dnolen: fliebel: ? what do you mean.

16:43 mattmitchell: wow i'm confused. i'm using the contrib.sql lib, and when i run a select w/a group_concat, the resulting field is a byte array. how the heck do i grab the actual values out of it? :|

16:44 fliebel: dnolen: well, they just write _::[] to mean whatever that means. So besides implementing that paper for the efficient dispatch, you also need the actual pattern matcher, right?

16:50 mattmitchell: ok clojure.core/slurp does the trick!

16:55 dnolen: fliebel: sorry, stepped away for a second, the decision tree is the pattern matcher.

16:59 fliebel: the predicate dispatch paper is all about building a decision tree with user definable predicates, the OCaml paper is about making a really, really efficient decision tree with the hard coded "predicates" that OCaml provides like _::[]. OCaml actually has guards which are like user definable predicates, but these are susceptible to ordering problems as I said before.

17:04 fliebel: dnolen: I too stepped away :) Umph, I understood little of the paper I guess.

17:04 dnolen: fliebel: I'm reading it for a 4th time now, it's starting to make sense.

17:05 fliebel: hehe :) okay, point made.

17:06 dnolen: fliebel: basically the gist of both papers is the same, the predicate dispatch comes from the perspective of OO and generic methods, the OCaml paper comes from the perspective of ML style pattern matching. But the methodology is very much the same, and the second paper really digs into how to make it very fast.

17:06 fliebel: does the other one also use that math syntax?

17:08 dnolen: fliebel: predicate dispatch perspective - we want pattern matching, but we want to be able add new patterns whenever we want. But they don't address the fact that new patterns might introduce ordering issues. So I want to the open-ness of predicate dispatch, the efficiency of ML pattern matching, and remove the ordering issue.

17:08 fliebel: no.

17:08 fliebel: They seem to be theorizing about tree depth and sharing. Would it make sense to write a pattern JIT? I mean, let the naive one run a few iterations, and optimize 'hot paths'.

17:09 In real life, some branches are more equal than others.

17:10 dnolen: fliebel: let the JVM do that for you.

17:11 it's just byte code.

17:13 fliebel: the other advantage with that paper is prior papers on ML pattern matching implementations are complex, while this paper presents a solution that's simpler to implement w/o losing on perf.

17:14 fliebel: dnolen: What I mean is that while these nice heuristics might figure out a tree that hash not to much decisions for all leaf nodes, there might be nodes that get accessed more frequently than others. So I was thinking you could shape the tree by usage, so that the common cases require few deciisions.

17:15 dnolen: Yea, the mentioned that it is simple and still works for anything but pairs.

17:18 * fliebel really needs sleep now

17:19 mattmitchell: what's the best way to convert a string "1" into an integer 1 ?

17:19 dnolen: fliebel: I know. a runtime optimization - so something I'd rather leave to JVM.

17:20 amalloy: &(read-string "1")

17:20 sexpbot: ⟹ 1

17:22 mattmitchell: amalloy: perfect thanks

17:30 raek: mattmitchell: if you only want to allow integers: ##(Integer/parseInt "1")

17:30 sexpbot: ⟹ 1

17:34 * raek finally checks out fnparse

17:42 mreynolds: I'm blanking on how to force a string to not be treated as a sequence. What's the function to dot hat?

17:43 mec: Is there anything better than (Object.) for a bunch of unique things to use in a map

17:43 as keys* in a map

17:43 mreynolds: what are you wanting to do with the string?

17:43 mreynolds: mec: Trying to create a sequence of strings, not chars

17:43 raek: mec: keywords with namespace parts could be an option

17:44 mreynolds: mec: Trying to build tests for a simple line parser

17:45 mec: mreynolds: so you want to split a string into smaller strings?

17:45 raek: mreynolds: could you show us the code where the problem occurs?

17:46 mreynolds: mec: Actually, I have test strings that I want to feed into a function that then splits them. I have the splitting part, but I want to build a test and that requires building up some test strings.

17:46 raek: mreynolds: there's nothing with strings that keep them from being part of sequences

17:46 mreynolds: raek: k, lemme see what I can do

17:49 mec: raek: I can't know how many ahead of time so I dont think I want to make keywords on the fly

17:51 raek: mec: then (Object.) sounds like a good fit to me

17:51 clojurebot: Excuse me?

17:51 raek: O_ô

17:52 amalloy: mec: (Object.) and (gensym) are the classics

17:52 mec: ah forget about (gensym), I think it would have more overhead tho

17:53 dnolen: gensym is actually quite slow.

17:53 mreynolds: raek: I think I'm running into a problem with printing at the console, not with sequences. One sec.

17:55 amalloy: (Object.) is surely "cheaper"

17:55 mec: I was just using numbers, but I figured eventually I would run out so I'd rather future proof :x

17:56 amalloy: but i bet if you want to debug it's easier to read ##(gensym) than ##(Object.)

17:56 sexpbot: (gensym) ⟹ G__37171

17:56 (Object.) ⟹ #<Object java.lang.Object@1bc2314>

17:57 mec: hmm, maybe a helper function that switches to (gensym) for debugging

17:58 mreynolds: raek: http://pastebin.com/tRb8z2Es

18:03 Ramblurr: is it possible to supress warnings when (use ..) ing?

18:03 raek: mreynolds: some comments: replace (String. "foo") with "foo" and == with =

18:04 mreynolds: raek: Yeah, I did for the affected test (realized the String. was irrelevant), and I had it as "=" before, but I thought == does contents equality?

18:04 raek: Ramblurr: are the warnings caused by your code? if so, you should fix the cause instead... :-)

18:05 Ramblurr: raek: yea they are, i know usually you would want to fix the cause, but in this case my goal is to make the code as small as possible

18:05 raek: mreynolds: == is a rare special operations for numbers. = does what you want

18:05 Ramblurr: raek: so replacing a function is better than using a namespace

18:05 raek: Ramblurr: what var is being replaced?

18:05 mreynolds: raek: k, thanks. Also, found my other bug which is pipe being a special char and I didn't comment it. Commenting it returns the right thing. However, if it fails to split, the function treats the original string as a sequence.

18:06 Ramblurr: raek: im replacing clojure.core/repeat with clojure.contrib.string/repeat

18:06 raek: ,(clojure.string/split "\"a\"|\"b\"|12345|12345678901234567890|\"long string\"|\"\"\n" #"\|")

18:06 clojurebot: ["\"a\"" "\"b\"" "12345" "12345678901234567890" "\"long string\"" "\"\"\n"]

18:06 raek: mreynolds: I get the string split into its parts

18:06 mreynolds: ,(clojure.string/split "\"a\"|\"b\"|12345|12345678901234567890|\"long string\"|\"\"\n" #"|")

18:06 clojurebot: ["" "\"" "a" "\"" "|" "\"" "b" "\"" "|" "1" ...]

18:07 raek: Ramblurr: and you want to use string's repeat instead?

18:07 mreynolds: mreynolds: That's the bug in my code with pipe.

18:07 Ramblurr: raek: yup

18:07 mreynolds: raek: Trying to remember the interaction of pipe as a regex, and if the original string is being returned as a sequence, or...

18:07 raek: if so, you should have (ns your-ns (:refer-clojure :exclude [repeat]) ...)

18:07 to make that clear

18:08 Ramblurr: raek: doing (use '[clojure.contrib.string :only (repeat)]) and then (repeat..) rather than (require ... :as s/repeat) is less code, but i get a warning :\

18:09 raek: ah nevermind, the error goes to stderr anyways

18:09 not stdout, so all is good

18:09 raek: thanks for that namepsace exclude tip

18:09 raek: for the user namespace in the repl, everything in clojure.core is already referred.

18:10 so it's hard to opt out certains vars in it...

18:11 Ramblurr: :exclude is the correct way to do it. the reason clojure show a warning instead of an error is to not break peoples' projects when new stuff enters clojure.core.

18:12 mreynolds: | in a regex means alternative, so you have to quote it like \|, as you did in your paste

18:13 mreynolds: raek: Gotcha, just trying to figure out why the original string gets treated as a sequence in taht case.

18:13 raek: mreynolds: but note that the order of the keys of a map is not maintained, so your equality check will probably fail

18:13 ,(clojure.string/split "\"a\"|\"b\"|12345|12345678901234567890|\"long string\"|\"\"\n" #"")

18:13 clojurebot: ["" "\"" "a" "\"" "|" "\"" "b" "\"" "|" "1" ...]

18:14 raek: mreynolds: it doesn't. you split at "nothing"

18:14 mreynolds: raek: Yeah, sorry, building up the test a piece at a time, wanted to jump over the sequence hurdle first

18:14 raek: Gotcha. This is my faulty memory of regex handling in java coming back to bite me

18:14 raek: the string matches nothing, followed by ", followed by nothing, followed by a, etc

18:14 mreynolds: raek: thanks

18:15 raek: one rule about regex *literals* in clojure is that their syntax is *exactly* as described in http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html

18:17 mreynolds: raek: Gotcha. I screwed this up when I did java too, so I don't blame clojure for that :)

18:18 mec: when should i use clojure.test/testing vs clojure.test/deftest

18:25 dakrone: mec: use deftest to declare a test, testing to declare sections of a test within a deftest

19:48 mreynolds: '(contains? (list "a" "b" "c") "a")

19:49 ,(contains? (list "a" "b" "c") "a")

19:49 clojurebot: false

19:49 mreynolds: Clojuredocs.org has a note on contains? saying they're not sure why that evaluates to false, does anyone here know?

19:50 raek: ,(contains? (list "a" "b" "c") 0)

19:50 clojurebot: false

19:50 technomancy: clojurebot: contains?

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

19:50 mreynolds: bah

19:50 I'll edit the page :)

19:50 technomancy: contains? is specifically designed to trick newbies into thinking about O(n) characteristics of data structures.

19:50 mreynolds: it worked!

19:51 technomancy: there is no other explanation for why it hasn't been renamed

19:51 mreynolds: brilliant. =)

19:54 dnolen: ,(associative? '(a b c))

19:54 clojurebot: false

19:54 dnolen: ,(associative '[a b c])

19:54 clojurebot: java.lang.Exception: Unable to resolve symbol: associative in this context

19:55 dnolen: ,(associative? '[a b c])

19:55 clojurebot: true

19:55 mec: ,(contains? '(a b c) 1

19:55 clojurebot: EOF while reading

19:55 mec: ,(contains? '(a b c) 1)

19:55 clojurebot: false

19:55 dnolen: ,(get '(a b c) 0)

19:55 clojurebot: nil

19:55 dnolen: ,(get '[a b c] 0)

19:55 clojurebot: a

19:56 mec: (nth '(a b c) 0)

19:56 ,(nth '(a b c) 0)

19:56 clojurebot: a

19:56 dnolen: ,(find '(a b c) 0)

19:56 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to java.util.Map

19:56 amalloy: i like that explanation, technomancy

19:56 dnolen: ,(find '[a b c] 0)

19:56 clojurebot: [0 a]

19:57 amalloy: &(doc find)

19:57 sexpbot: ⟹ "([map key]); Returns the map entry for key, or nil if key not present."

19:58 amalloy: neat. i didn't know about that one

20:01 mec: useful if your map's values might be nil

20:01 well i guess thats what not-found is for anyway

20:10 pdk: that sorta thing

20:10 is why i miss multiple-value-bind sometimes

20:18 mec: is that a language feature or built onto CL?

20:19 amalloy: i think it must be a language feature. pasting it on with other CL primitives would be gross

20:20 mec: you could do it it with with-bindings and 2 macros

20:24 amalloy: i don't think you could do it in a way that is both transparent to non-mvbind contexts and performant. i implemented mvbind in clojure a couple different ways for fun, and they're not very good; i'd be interested to see the way you do it

20:24 mec: sure, working on it now

20:27 what are the 2, mutiple-value-bind and values?

20:38 whats the difference between binding and with-bindings and how do you use either

20:42 https://gist.github.com/949291

20:42 ^^ multiple-value-bind

20:53 amalloy: mec: with-bindings is lower-level. wants vars instead of symbols

20:54 mec: well its about 12 times slower than directly using let

20:54 amalloy: mec: i'm not convinced by your solution. it doesn't work to have (values (some-other-mv-function) true), because some-other-mv-function will see the global value of *multi-value*

20:55 ie, you only support one multi-valued function globally at a time - they don't nest

20:55 mec: ah hmm

20:55 amalloy: very neat prototype though. not a way i'd considered doing it

20:57 mec: no idea how to fix that

20:58 other than to wrap ~vals in (binding [*multi-value* false] ~vals)

21:08 chrissbx: What's the best way to fold over a sequence two elements per step? Like for example the vector with the variables+expressions in a let form.

21:09 mec: any idea why this would throw a null pointer? (when (sequential? x) (= (seq x) (seq this)))

21:09 chrissbx: (partition 2 coll)

21:10 so (reduce (fn [[k v]] ...) (partition 2 coll))

21:14 chrissbx: Thanks. Any way to get error checking for (partition 2 '(k1 v1 k2)) ?

21:14 (Without me doing length calculations around it?)

21:14 mec: (let [kvs (partition 2 coll)] (if (odd? (count kvs)) (throw ...)))

21:15 oh

21:16 chrissbx: well, whatever. I guess I'm just supposed to do it that way.

21:16 mec: (reduce (fn [[k v :as t]] (if (= (count t) 1) (throw Exception.) ...) (partition 2 coll))

21:16 s/partition/partition-all/

21:16 sexpbot: <mec> (reduce (fn [[k v :as t]] (if (= (count t) 1) (throw Exception.) ...) (partition-all 2 coll))

21:17 chrissbx: I always prefer solutions that I can use without caring about errors and that then don't just suppress them.

21:17 But since clojure even doesn't think (first '()) is an error, then I guess my code will never be fool proof anyway.

21:18 I suppose I better get over it.

21:19 mec: its pretty handy that a lot of stuff returns nil instead of exceptions

21:20 chrissbx: Well, at the cost of missing (early) error checking.

21:21 (But partition doesn't even return nil, it just returns part of the solution.)

21:22 mec: ya partition truncates, gotta use partition-all if you want partials

21:23 amalloy: mec: actually i think that's a sufficient fix. wrapping values, that is

21:23 clojurebot: partition?

21:23 clojurebot: partition is probably not what you want; see partition-all.

21:23 mec: lol

21:24 amalloy: chrissbx: forget about (first ()), clojure is perfectly happy with ##(first (first (rest (first nil))))

21:24 sexpbot: ⟹ nil

21:24 chrissbx: Well, using partition-all will just sweep the error under the carpet in the subsequent reduce.

21:24 amalloy: &(doc partition)

21:24 sexpbot: ⟹ "([n coll] [n step coll] [n step pad coll]); Returns a lazy sequence of lists of n items each, at offsets step apart. If step is not supplied, defaults to n, i.e. the partitions do not overlap. If a pad collection is supplied, use its elements as necessary to complet... http://gist.github.com/949317

21:25 mec: ok i changed equiv on this deftype to (equiv [this x]) and it still throws a null pointer when called

21:25 amalloy: chrissbx: pass a "pad" collection that's something like (repeatedly #(throw (Exception. "OMG WUT")))

21:25 &(partition 2 2 (repeatedly #(throw (Exception. "OMG WUT"))) (range 4))

21:25 sexpbot: ⟹ ((0 1) (2 3))

21:25 amalloy: &(partition 2 2 (repeatedly #(throw (Exception. "OMG WUT"))) (range 5))

21:25 sexpbot: java.lang.Exception: OMG WUT

21:26 mec: wow thats interesting

21:26 amalloy: that still delays the exception until the first wrong-sized partition, but you can't do any better than that and still be lazy

21:27 mec: why does partition do that instead of just passing the function

21:27 amalloy: mec: ?

21:27 mec: ah nvm

21:33 amalloy: chrissbx: anyway you can (defn die [] (repeatedly #(throw...))), and then use (die) as your pad collection

21:33 to let you fail as fast as is possible

21:33 chrissbx: well, (def die (repeatedly ...))

21:34 But since I'm used not to bother about edge cases when writing my code, I'll forget about this.

21:34 amalloy: chrissbx: i considered that, i don't think it's a good idea

21:34 chrissbx: And my code will just do unsensible stuff as a consequence.

21:34 And I don't care right now :)

21:35 amalloy: if you use the same lazy-sequence of exceptions and someone ever catches one of them, that first result gets cached and probably would result in silent failures

21:35 chrissbx: What would be cached isntead of the exception?

21:36 ah the result of the exn handler, you mean?

21:36 amalloy: i'm not sure, really. it's a weird case

21:36 chrissbx: heh

21:36 mec: mine keeps blowing up

21:36 chrissbx: mec: amalloy means when you use an exception handler that replaces the exn with a value

21:37 amalloy: yeah, but i was wrong

21:37 there's no way it could get cached

21:37 chrissbx: If that's possible in Clojure to have such a handler at all.

21:39 amalloy: no, it's not

21:39 the stack unwinds up to the first handler it can find, and grows anew from there

21:41 chrissbx: How do debuggers work, though, if an exception happens? They'll have to capture it with the stack before unwinding.

21:41 amalloy: they attach to the process externally

21:41 chrissbx: (Or have access to the unwound stack after-the fact.)

21:42 (To the un-unwound, I meant)

21:42 amalloy: and then the jvm gives them priority execution while the target program is suspended

21:42 chrissbx: k

21:43 Maybe that'll be a feature in a future Clojure version (for restarts ...).

21:44 Then my code will break then :)

21:45 My future is already doomed while learning Clojure.

21:45 amalloy: eh?

21:49 chrissbx: Just exaggerating.

22:26 semperos: informational question: what do folks think would be interesting metrics to "calculate" from scanning all of Clojure's IRC logs for the last three years?

22:34 mec: semperos: number of unique visitors could be interesting

22:35 semperos: mec: thanks

22:35 any thoughts on "equivalent" nicks? by default i was thinking "foo" and "foo_" with any number of underscores

22:36 mec: also ` and preceding _

22:37 semperos: ` at the end?

22:37 I've been brainstorming a few things, esp. around clojurebot/sexpbot use, specific Clojure fn's, folks who talk the most, folks "on" most number of days

22:37 things in that vein

22:48 chrissbx: semperos: you might catch most nick duplicates by checking for renames

22:48 semperos: true

22:49 actually using the logs saved at n01se.net for this, where those aren't captured

22:49 chrissbx: ah

22:49 semperos: but a fine thought

22:51 here's what I have so far after a quick brainstorm:

22:51 * Total unique visitors

22:51 * Total messages

22:51 * Total mentions of particular languages (Java, Ruby, Lisp)

22:51 * Clojurebot vs Sexpbot use

22:51 * For a user, total messages

22:51 * For a user, total days "online" (at least one message)

22:51 * Top users

22:51 * Top days (number of messages)

22:51 * Top Clojure fn's mentioned/used

22:51 was hoping that wouldn't make separate messages...

22:52 obviously there'll be ambiguity, but this is a start

22:53 * For a user, number of messages including Java interop forms

22:59 chrissbx: Another fine thought might be to ask for the source files used by n01se.net, esp. since there seems to be a parser for those at https://github.com/Chouser/clojure-irc-log

Logging service provided by n01se.net