#clojure log - Mar 05 2011

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

0:50 amalloy: hm. i wind up defining a lot of functions that are basically just (defn foo "docs" [args] (f1 (f2 (f3 args))))

0:51 i could write like a defcomp macro that lets me write this as (defcomp foo "docs" [args] f1 f2 f3); do people think this would be more or less readable?

0:51 pdk: dude

0:52 (apply (comp f1 f2 f3) args)

0:52 amalloy: pdk: what's your point?

0:52 should the caller do that instead of my function ever existing, or should i write that in the body of my defn?

0:53 pdk: though a general form for writing fns that just compose others like that and return the values they return would be useful so i'd go with this defcomp idea

0:53 amalloy: the former is clearly silly imo, and the latter is nonoptimal if args is a long list

1:01 huh. despite having recently helped someone with this in #clojure, i can't seem to get a macro to def something with specific metadata

1:23 pdk: can you explain to me why i need the ' in https://gist.github.com/856176 - it seems like the arglists are being evaluated at expansion time, not evaluation time, but it doesn't work without '

1:38 tomoj: seems like it's specific to def

1:38 take (defmacro notdefcomp [name args] (with-meta name {:arglists (list args)}))

1:38 same thing, really, no errors

1:39 err.. not the same thing. but I'd have guessed the error would show up in both or neither

1:44 iwillig: hi, i can't seem to figure this out. But I have an Java class that I want to extend to implement ISeq

1:44 does any one have any pointers ?

1:45 tomoj: yeah, stack trace from DefExpr suggests compiler weirdness

1:45 damn you for puzzling me

1:46 iwillig: this is my start

1:46 https://gist.github.com/856189

1:46 tomoj: hmm, maybe not that puzzling

1:46 (do (def xyz "foo") (def ^xyz bar 3) (meta #'bar))

1:47 nah, I'm still puzzled

1:47 iwillig: ISeq is an interface, I think you're out of luck

1:48 iwillig: mmm

1:48 tomoj: this is why protocols were invented :)

1:48 unfortunately until cinc the expression problem remains in clojure's core

1:49 iwillig: so there is no way to extend an Java type to take advantage of clojure seq libraries

1:49 ha

1:50 i guess i could use reify

1:50 err i mean proxy

1:50 tomoj: why do you want points to be seqs anyway?

1:50 iwillig: but that does not really solve my issue

1:50 good question

1:51 i think it makes things a lot easier

1:51 so with an Point object is not such a big deal

1:52 tomoj: maybe work with vectors and convert to Points at your clojure-java bridge?

1:52 and vice-verso

1:52 iwillig: brb

1:54 amalloy: tomoj: yeah, i would have guessed the same

1:55 in fact i tried (list args) first; i imagine i could have written (list 'quote (list args)) or something but `' seemed clearer

1:55 tomoj: my example was just a short way to cause the error

1:55 (or not)

1:57 but let's see

1:57 your macro is expanding to, say (def foo ...)

1:57 and the metadata is already on foo

1:58 nope, thought I made sense of it again, but I keep coming back to: it's just a damn list

1:58 amalloy: tomoj: exactly

1:58 tomoj: coming back to that from: it's the same as (def ^{:arglists [a b c]} foo ..)

1:58 amalloy: i tried macroexpanding it, and it happily expands to (def foo (comp ...))

1:58 tomoj: but that looks different to me now

1:59 amalloy: but for some reason the meta on foo gets evaled when i eval the def

1:59 tomoj: &(meta (second '(def ^{:arglists ([a b c])} foo)))

1:59 sexpbot: java.lang.SecurityException: You tripped the alarm! def is bad!

2:00 tomoj: I need to give up

2:01 amalloy: you tripped the alarm! giving up is lame!

2:01 tomoj: if you crack it, let me know - feel like there's a bit of metadata/macro enlightenment involved

2:01 :)

2:01 amalloy: tomoj: i thought i'd cracked it a couple days ago, but what worked then doesn't work now :P

2:02 tomoj: I see something in Compiler.java that seems relevant (DefExpr analyzing the metadata)

2:02 but don't have the patience to try to understand Compiler.java right now

2:02 amalloy: maybe i'll take my own advice, and put a ;;TODO wtf why does this work

2:02 tomoj: does it, though?

2:03 with your version I end up with {:arglists (quote [a b c])} or something like htat

2:03 amalloy: my version works the way i want it to

2:03 tomoj: ooh

2:04 amalloy: slime gives me arglist prompts, etc

2:04 tomoj: (meta (second (macroexpand-1 '(defcomp foo "bar" [a b c] inc dec))))

2:04 then it's eval'd to the right thing, I see

2:05 I can't help but think again that that is just like you'd have to (def ^{:arglists '[a b c]} foo)

2:05 and of course shortly after thinking that I'm just as confused :(

2:05 amalloy: yes, and that works outside a macro

2:05 if i `(def ^{...} ~name ...) inside the macro, no good

2:09 tomoj: yeah, but

2:09 no, nevermind. giving up.

2:10 amalloy: lol

2:10 i felt that way too

2:10 tomoj: I thought I understood metadata and I thought I understood macros

2:10 but together...

2:10 amalloy: hahahaha

2:11 Learn, Internalize, Surprise, Perplex

2:12 tomoj: iswydt

2:13 * amalloy is not that subtle

2:14 khaliG: has anyone integrated icanter into their own app?

3:13 clojurebot: PONG!

3:13 Invalid token: /3

3:13 #<core$constantly$fn__3551 clojure.core$constantly$fn__3551@b670cd>

3:13 c'est bon!

3:13 42

3:13 what is cells

3:13 java.lang.NullPointerException: Expecting Symbol + Namespace

3:13 42

3:13 multimethods is what separates the boys from the men.

3:13 Ptival: wow clojurebot speaks French

3:15 tomoj: :D

3:16 I think that was a

3:16 6 hour delay

3:16 or so

3:17 Ptival: extreme buffering

3:18 tomoj: hiredman: how?!

3:33 amalloy: nice

3:34 tomoj: the tubes were all blocked up

3:35 ~testing42

3:35 clojurebot: 42

3:35 amalloy: ~botsnack i guess? kinda hard to say

3:35 clojurebot: thanks; that was delicious. (nom nom nom)

3:35 amalloy: anyway night folks

3:35 tomoj: i put my macro confusion on the google group. we'll see if anyone has ideas

6:56 fmw: how do you write something to the extend of 'if foo == "bar" or foo == "foobar"' in clojure? i.e. an if with multiple clauses.

6:56 mrBliss: ,(let [foo "bar"] (if (#{"bar" "foobar"} "bar") 1 2))

6:56 clojurebot: 1

6:57 fmw: mrBliss: thanks!

6:57 mrBliss: (don't mind the let clause)

7:02 pyr: hey

7:42 fmw: mrBliss: hmm, I'm still trying to wrap my head around that line, but it seems like it isn't a good fit for what I'm trying to do (not your fault, obviously, because I should've been more precise)

7:42 basically I'm trying to make http://paste.pocoo.org/show/348413/ more concise

7:42 as you can see from that paste, I'm trying to learn Clojure by porting some Python code.

7:43 bawr: fmw: That's probably not a good idea. Rewriting from scrach, maybe. Porting, not so much. ;)

7:43 raek: fmw: you can use the or and and not macros to form compound conditions

7:43 fmw: bawr: In this context I mean rewriting when I say porting ;)

7:44 mrBliss: fmw: I can see that ;-) In Clojure, one does not use def for local variables. (Gotta grab dinner now)

7:44 fmw: mrBliss: thanks, I'll read up on the local variables thing :)

7:44 raek: if foo == "bar" or foo == "foobar" would be written (if (or (= foo "bar") (= foo "foobar")) ... ...)

7:44 __name__: fmw: what about (and (integer? n) (> n 0))

7:44 fmw: raek: ah, those macros are exactly what I need

7:45 __name__: fmw: instead of positive-integer?

7:45 raek: there's even 'pos?'

7:45 fmw: you can use let to introduce a named value for a scope: (let [x 1] ...code that uses x...)

7:46 bawr: raek: Just do be sure, nested defns are okay if they make the code more clear, right? :)

7:46 Or is that a schemism?

7:46 raek: you can think of it as { int x = 1; ...code that uses x... } in C, only that you can only assign once...

7:46 fmw: raek: so def for global variables, let for vars in the local scope?

7:47 or rather, global to the namespace

7:47 raek: bawr: no, nested defn probably does not do what you think

7:47 def defines a *global* variable

7:47 unlike define in scheme

7:48 you can use private global defn if you want helper functions: (defn- helper-fn [x] ...)

7:48 bawr: SO something like (defn mangle [x y] (defn mingle [i] (+ i y)) (map mingle x)) is bad?

7:48 Oooh.

7:48 fmw: ah, so thats what the - after defn is for

7:48 raek: or you can use let or letfn: (defn f [x] (let [g (fn [y] ...)] (g (inc x))))

7:49 fmw: seen that in a lot of library functions

7:49 raek: bawr: yes.

7:49 two invokations of the same function will overwrite the other one's sate

7:49 *state

7:49 bawr: raek: Hey, thanks.

7:50 raek: a rule of thumb: a def form should never be executed at runtime

7:50 bawr: Aha, gotcha. I was just looking for a solution cleaner than a towering abomination of adding arguments with partial.

7:51 raek: (the above example with letfn: (defn f [x] (letfn [(g [y] ...)] (g (inc x))))

7:51 fmw: __name__: yes, thanks for that line, its a better approach.

7:52 raek: fmw: also, you usually write just (> n 0) instead of (if (> n 0) true false)

7:54 fmw: raek: as in leave out the if macro and the parenthesis block after (> n 0) is only evaluated if (> n 0) is true?

7:55 raek: hmm, seems like I misunderstood you there, because (> n 0) doesn't work on its own

7:56 raek: ,(let [x 5] (> x 1))

7:56 clojurebot: true

7:56 raek: it is an expression

7:56 well, everything is an expression in clojure

7:57 the if does not add anything in that case

7:59 fmw: raek: ok, but you do need if (or a similar macro) if you want to execute something based on the boolean value, right?

7:59 just not to get a boolean?

8:00 raek: yes

8:00 fmw: ok, that clears it up

8:00 BTW, thanks for answering all these silly questions ;)

8:00 raek: the special form 'if' lets you control which branch that will be evaluated

8:01 np

8:36 fmw: in clojure you usually structure the code so that each function returns the value of interest, rather changes global variables.

8:36 fmw: raek: are you the one that just replied to my paste with a better version?

8:37 raek: http://paste.pocoo.org/show/348431/

8:37 this one?

8:37 fmw: yes

8:37 raek: yes, I was just going to say that I took the liberty

8:37 of showing what a funcitonal solution might look like

8:37 fmw: raek: cool, I'm reading it as we speak :)

8:37 raek: functional programming is very different from imperative programming and it takes time to adjust to the thinking

8:38 fmw: raek: I just cleaned it up a bit already (see http://paste.pocoo.org/show/348433/), but I'll go over your functional version of the code

8:39 raek: yes, clearly. it is a very different approach and a good thing to be forced to wrap my head around while learning clojure

8:46 raek: I'm slowly digesting the code code you wrote right now (the general concept as well as functions I wasn't previously familiar with, e.g. update-in) and its starting to become more clear to me

8:46 raek: I really appreciate the fact that you took the time to write this

8:46 khaliG: i'm looking for some advice for integrating incanter into my clojure app. i'd like to draw a chart, how should i best go about this task?

8:48 raek: fmw: I wanted to tell you that you should never use def in the body of a function, but without an example on how to do otherwise, I guess that wouldn't be very helpful

8:48 khaliG: i know incanter can draw charts onto a new window, but if possible i'd like to have them done in a JPanel of mine.

8:49 raek: this video "Clojure Concurrency" explains the rational for the "mutable variables has to go" approach taken by clojure

8:49 http://clojure.blip.tv/file/812787/

8:51 fmw: raek: yes, I took your suggestion to use let instead of def to heart in http://paste.pocoo.org/show/348433/ , but didn't get further than replacing one def because I was still following the some approach as I would in other languages I'm familiar with, instead of the functional paradigm.

8:51 but the example you wrote sort of make the functional approach click with my brain

8:53 ok, watching the video now :)

8:58 khaliG: hm i might just do it by hand using Java 2D, will give me a bit more practice writing clojure anyways

9:06 raek: khaliG: I just found this, but I don't know how much it helps: http://clojuredocs.org/incanter/incanter.core/data-table

9:17 khaliG: raek, oooh that is cool. i'll remember for that later :)

9:18 fliebel: raek: What are these magic datasets?

9:19 raek: fliebel: in the pocoo paste?

9:20 fliebel: also, you mentioned something re my blog post yesterday. was something written in a misleading way?

9:23 fliebel: raek: poco? No just in general, Incanter seems to be using 'datasets' a lot, I was wondering what they are.

9:24 raek: I dunno :-) haven't used incanter much

9:24 fliebel: raek: Your blog post… I'm not sure. I was trying to figure out how the thread pools behind feature work. You said it is the same pool used by agents, but only by send-off. So I was 'tricked' into thinking that future would use a fixed pool.

9:26 raek: yeah, agents have two pools and of them (the non-fixed one) is shared with future

9:27 fliebel: I figured :)

9:42 TimMc: Haha, I'm glad I checked the scrollback! clojurebot, you so silly.

9:48 __name__: fmw: np

10:14 khaliG: hm ive tried close to everything to no avail. How the eck does one instantiate java.awt.geom.Line2D.Double

10:14 (in clojure that is)

10:16 ooh got it, it needs a dollar sign :)

10:16 raek: khaliG: java.awt.geom.Line2D$Double

10:16 ah, you figured it out...

10:16 khaliG: raek, thanks

10:21 pyr: can't you import java.awt.geom.Line2D Double :as Something ?

10:23 TimMc: pyr: I wish.

10:23 It would make working with AffineTransform in hinted code a lot nicer.

10:24 pyr: 'k

10:24 i thought that would be possible

10:24 but if i get this right

10:24 this is only a real concern for class names which clash with (like some.thing.foo.String or java.awt.geom.Line2D.Double)

10:25 s,with,with standard names from java.lang

10:26 TimMc: pyr: Nota bene: The compiler will sometimes refer to Point2D$Double as Double in error messages.

10:26 pyr: luckily my clojure stuff relies on very few java libs

10:26 but good to know

10:27 TimMc: I'm writing a Swing program, so... yeah.

10:48 fliebel: What is the syntax for version ranges in lein/cake?

10:49 https://github.com/cgrand/moustache/commit/c2a8adef899f08b0847b1e7feb9d2367efdbbbf7

10:50 raek: fliebel: same as in maven: http://maven.apache.org/plugins/maven-enforcer-plugin/rules/versionRanges.html

10:50 "If you've confirmed that your project will work with a number of different versions of a given dependency, you can provide a range instead of a single version."

10:50 "Don't do this unless you have manually confirming that it works with each of those versions though. You can't assume that your dependencies will use semantic versions; some projects even introduce backwards-incompatible changes in bugfix point releases."

10:51 from the leiningen tutorial

10:51 fliebel: raek: I understand the implications, just curious.

10:53 raek: It seems that just the version number is already a range? How is that...

10:56 bawr: What should I read if I want to understand cake, as opposed to just using it? I've had no real experience writing anything big in Java before.

10:58 fliebel: raek: Using a range is just as bad as using a snapshot, right?

10:59 raek: I have not used it for my own projects

11:00 but I belive version ranges are legitimate to use in stable releases

11:00 unlike SNAPSHOT dependencies

11:07 TimMc: Mature dependency managers like Firefox and APT use version ranges quite successfully.

11:07 Cozey: Hi! Is there some clojure community favourite alternative to SASS language for generating css?

11:07 fliebel: Cozey: I think someone wrote one, but it's not in wide use, like SASS.

11:08 Cozey: mhm

11:11 fliebel: Cozey: It's practically just a serialization of a map.

11:12 Cozey: :-)

11:24 gfrlog: algorithms trivia: it's possible to detect an arbitrarily long cycle in an (iterate) seq using constant space

11:24 fliebel: gfrlog: … how?

11:25 gfrlog: create two seqs, and consume one twice as fast as the other

11:25 if there's a cycle, they will eventually have identical heads

11:26 learned that in my crypto class; was part of some factoring algorithm

11:26 a bit of wikipedia clicking reveals: http://en.wikipedia.org/wiki/Floyd's_cycle-finding_algorithm#Tortoise_and_hare

11:27 fliebel: gfrlog: But, how do you know it is not the same head 'by accident'?

11:27 gfrlog: fliebel: if they're the same head, that means that head value comes up twice

11:27 DespiteItAll: fliebel -- it's iterate, so it doesn't matter :)

11:27 gfrlog: exactly

11:27 once you know a value comes up twice, you know it cycles

11:28 fliebel: gfrlog: But how do you know one cycle does not include the same head twice?

11:28 gfrlog: if you're iterating with a pure function, that's impossible

11:28 fliebel: hm…. that is true

11:31 gfrlog: And what about the time? That is everything but constant, but I wouldn't know how to express it.

11:32 gfrlog: fliebel: I think it will take perhaps up to twice as long as if you had infinite memory and could just hold all the past values

11:32 DespiteItAll: you could be iterating for a LONG time before they sync up. reminds me of steve reich's early works

11:33 gfrlog: I think it depends on the size of the cycle? once both seqs are inside the cycle, you shouldn't spin around more than one extra time

11:33 you also have to include the fact that each iteration is being performed twice instead of once

11:34 but even for cycles of manageable size, I would think it still has a chance at being faster than caching, as it uses so little memory

11:34 __name__: What's the difference between the PersistentHashMap and the PersistentArrayMap?

11:34 gfrlog: __name__ the array map is sorted sorta

11:34 __name__: sorta?

11:34 gfrlog: and also has linear lookup time

11:35 __name__: Instead of O(log32 n)

11:35 gfrlog: yeah I was reading about it just yesterday. By sorta I mean that it somehow gets out of order if you assoc onto it

11:35 __name__: yes

11:35 __name__: gfrlog: Do you have any resources on how the ArrayMap works?

11:35 gfrlog: docs say it's only appropriate for tiny maps

11:35 fliebel: gfrlog: Have you tried implementing the cycle thing in Clojure?

11:35 gfrlog: yeah let me find what I was reading

11:35 __name__: I understand the way the HashMap works, kind of,

11:35 gfrlog: fliebel: no, but I'd think it'd be trivial

11:35 __name__: It's just a tree after all

11:35 gfrlog: Thanks!

11:36 gfrlog: __name__: http://clojure.org/data_structures#Data Structures-ArrayMaps

11:36 __name__: Links with spaces :(

11:36 fliebel: __name__: the array version is simple as well, just iterate until you find the correct key.

11:36 __name__: Ah, that's trivial.

11:36 I read constant instead of linear …

11:37 fliebel: __name__: So it is only used for maps smaller than 16 items

11:37 __name__: fliebel: The interpreter decides which to use?

11:37 Oh, no, you do.

11:37 gfrlog: __name__: I think it's mostly used in the implementation of certain things. I've never used one directly myself.

11:38 __name__: gfrlog: Normal sorted-maps are trees too, right?

11:38 gfrlog: __name__: probably

11:38 __name__: I hate this printing dialogue :(

11:38 gfrlog: __name__: I think they're performant, so I'm sure that's the case

11:38 __name__: you hate chat rooms?

11:39 __name__: gfrlog: no, the printing thing of firefox.

11:39 gfrlog: hmmm...don't know what that is

11:39 __name__: When you press Ctrl-P, a dialog window opens.

11:40 gfrlog: why else would you press it?

11:40 __name__: gfrlog: That dialog refuses to let me choose A4 :(

11:40 I don't want stupid letter :(

11:40 gfrlog: fliebel: this would do it, right? https://gist.github.com/856492

11:41 __name__: oooh -- I thought you hated that Ctrl-P opened the dialog. I guess you hate the dialog itself. That's fine.

11:41 __name__: :)

11:41 gfrlog: down with the firefox print dialog!

11:42 fliebel: I guess it's a bit weird to name it as if it's a predicate, since it never returns false

11:42 it's like the halting problem...

11:43 fliebel: gfrlog: I can;t see it, because a Java applet is obscuring my view :S

11:43 pdk: name it return-true

11:43 it'll be fun

11:43 gfrlog: pdk: :-D

11:44 cycle detection? that's what the return-true function does of course. Don't you understand the naming conventions?

11:44 TimMc: (defn did-not-throw-error? [] true)

11:44 gfrlog: hah

11:44 fliebel: gfrlog: ##(doc nnext)

11:44 sexpbot: ⟹ "([x]); Same as (next (next x))"

11:45 gfrlog: ah I knew it

11:45 I was about to rewrite it with destructuring actually

11:45 fliebel: gfrlog: Will that solve the duplicate itterate?

11:46 TimMc: wait wait

11:46 (defn did-not-throw-error? [] (if (> (rand) 0.5) (throw (Exception. "Oops!")) true))

11:46 gfrlog: https://gist.github.com/856492

11:46 fliebel: no

11:46 you have to duplicate iterate

11:46 fliebel: because with (defn really-huge [] (sleep long)) it will take twice the time.

11:46 gfrlog: yes, I think the duplication is inescapable

11:47 it's what you sacrifice for the memory benefits

11:47 that code got a LOT shorter with destructuring...

11:47 fliebel: gfrlog: But not duplicate the effort. I thin a lazy seq keeps the realized elements somewhere as state, so letting the itterate will help.

11:47 oh… hm

11:48 gfrlog: fliebel: you don't want anything cached or your memory will blow up

11:48 fliebel: So I think letting the iterate will kill you


11:48 fliebel: probably...

11:48 http://xkcd.com/725/

11:48 gfrlog: keeping track of all the in-between values eventually gets too much

11:49 fliebel: hm

11:49 gfrlog: fliebel: well played

11:49 that comic confirst that I spelled literally correctly

11:50 I literally spelled it correctly

11:50 s/confirst/confirms

11:50 sexpbot: you can't look back one extra comment? just one?

11:50 clojurebot: teach sexpbot how to respond to direct messages

11:50 clojurebot: sexpbot is not a clojurebot

11:51 TimMc: nice

11:51 fliebel: gfrlog: So, what about the destructuring?

11:51 gfrlog: fliebel: I don't know what that question means. What about it?

11:51 I was just saying it made the code cleaner

11:51 fliebel: gfrlog:Can I see it :)

11:52 gfrlog: oh I gave a link

11:52 https://gist.github.com/856492

11:52 I haven't tested either of those functions

11:53 I will paste it into the repl right now and see what happens

11:53 fliebel: The hardest part is defining a function that does a cycle :P

11:54 gfrlog: => (return-true #(rem (inc %) 83800) 88)

11:54 true

11:54 also:

11:54 => (return-true #(rem (* % %) 83879) 88)

11:54 true

11:55 doing anything at all within a fixed domain will have to cycle

11:55 e.g., any hash function

11:56 fliebel: hash function?

11:56 gfrlog: hash function

11:56 fliebel: $google hash function

11:56 sexpbot: First out of 551000 results is: Hash function - Wikipedia, the free encyclopedia

11:56 http://en.wikipedia.org/wiki/Hash_function

11:56 clojurebot: #<RuntimeException java.lang.RuntimeException: java.lang.Exception: 503>

11:56 gfrlog: :)

11:57 who told clojurebot to do anything?

11:57 ,"I dunno"

11:57 clojurebot: "I dunno"

11:58 gfrlog: fliebel: hash functions are good.

11:58 they're one of my favorite things.

11:59 TimMc: clojurebot randomly throws that 503 exception on URLs

11:59 gfrlog: ooh

11:59 http://github.com

12:00 maybe it only accepts URLs from sexpbot

12:00 sineer: Hi! I am going nuts trying to setup swank-clojure Classpath!! Someone Please Tell Me Why no matter how hard I try to set the swank-clojure-classpath var it always end up set as: (swank-clojure-default-classpath) instead of whatever I try to set it to...

12:01 Even this won't work: (eval-after-load "swank-clojure" '(progn (add-to-list 'swank-clojure-classpath "~/.emacs.d/site-lisp/swank-clojure/src/")))

12:01 fliebel: gfrlog: Hm, I want to see what the cycle part was...

12:01 sineer: I've spent the last 2 hours trying to fix this :(

12:03 in swank-clojure.el... this line: (defcustom swank-clojure-classpath

12:03 (swank-clojure-default-classpath)

12:03 can this prevent me somehow from using add-to-list ?

12:04 gfrlog: fliebel: you mean why I say a hash function will cycle?

12:04 fliebel: gfrlog: No, I ran a cycle, and I wanted to see when it started to repeat.

12:05 gfrlog: oh...add some prints?

12:05 if you run the return-true function with a hash function you will probably never see it repeat

12:05 unless it's a bad hash function

12:07 fliebel: user=> (return-true #(.hashCode (str %)) "hallo wereld") => true

12:09 gfrlog: ^

12:09 gfrlog: fliebel: will have to check what .hashCode does

12:10 ah yes

12:10 fliebel: gfrlog: but for (defn return-truthy [it ob] (let [[f & r] (iterate it ob)] (take-while (partial not= f) r))): (doall (return-truthy #(.hashCode (str %)) "hallo wereld")) => java.lang.OutOfMemoryError

12:10 gfrlog: so for certain purposes you can use bad hash functions

12:11 .hashCode is a bad hash function

12:11 fliebel: why?

12:11 clojurebot: why not?

12:11 gfrlog: because its range is 256 I believe

12:11 or maybe 2^32

12:11 both of which are small

12:11 for crypto purposes

12:12 they are fine for programming language purposes like hash maps

12:12 fmw: raek: just watched the whole 2:32+ hours of that with a short break to read over the concepts he was talking about in my "Seven Languages in Seven Weeks" book. I guess I learned a lot, but the information is still working its way to seep through the cracks in my brain ;)

12:12 raek: thanks

12:12 gfrlog: which I believe is the expected usage

12:12 when I said 'would never return' I was referring to any crypto hash function, which would have a much bigger range

12:13 fliebel: gfrlog: But why does it return true instantly for you function, and not at all for mine?

12:13 oh, wait, I know...

12:14 gfrlog: you're letting the iterate, right?

12:15 another reason that algorithm might not work is that the first object in the iterate doesn't have to be part of the cycle

12:15 fliebel: gfrlog: I'm doing something completely different, namely, looking if the first value comes back later.

12:15 gfrlog: (btw, in your code f == ob)

12:16 right

12:16 okay then, as long as it's on purpose

12:16 I would guess for a given hash function there is a good chance the initial value will not show up again

12:17 also, take-while will probably keep the whole seq

12:17 another cause for the memory error

12:17 fliebel: gfrlog: *That* was intended. I wanted to see the whole cycle.

12:17 gfrlog: man I'm always incorrectly guessing your intentions

12:18 ,(.hashCode "fliebel")

12:18 clojurebot: -771880729

12:18 gfrlog: looks like the range is 2^32

12:18 fliebel: Maybe I'm just not clear in my intentions ;)

12:18 gfrlog: so that'd be too big

12:18 if you use #(rem (.hashCode %) 256)

12:18 as the hash function

12:18 it would cycle much faster

12:18 adjust 256 to your liking

12:19 fliebel: yea...

12:23 victory! I changed true into a in your code, and used that in mine :)

12:24 gfrlog: but mine doesn't keep all the values...

12:24 fliebel: 1018032231 has a cycle of 37525

12:25 gfrlog: did you use the raw hashCode or reduce it?

12:25 fliebel: raw

12:25 gfrlog: huh

12:26 I have a visual javascript implementation of SHA-1 that I need to clean up and publish

12:35 ApeShot: So I'm using lein, and I have a "general purpose" library in one project and a specific project that depends on it, and I am working in the project directory, but want clojure/swank-clojure to handle things correctly when I update the utility library

12:35 There is a specific idiom for this that I can't remember, as I've been in CL land for awhile.

12:35 I put a symlink somewhere?

12:36 I'm in emacs and on ubuntu

12:36 checkout dependencies, it seems, is the answer

12:36 Thanks!

12:37 gfrlog: man I can never remember whether the reader macro is ~@ or @~

12:37 ~@ apparently

12:37 clojurebot: @ is splicing unquote

12:38 gfrlog: so if you want to unquote the result of derefing something... you add whitespace?

12:38 ,`~(deref (atom 0))

12:38 clojurebot: 0

12:38 gfrlog: ,`~@(atom 0)

12:38 clojurebot: splice not in list

12:38 gfrlog: ,`~ @(atom 0)

12:38 clojurebot: 0

12:38 gfrlog: guess so

12:41 ApeShot: Ok, so using checkout dependencies, do I need to add something to my project.clj file to reflect that dependency or does Lein keep track of it itself/

12:41 raek: ApeShot: iirc, you should include the library in :dependencies as usual

12:42 ApeShot: raek: what do I write for a personal library?

12:43 raek: and in addition to that, have a symlink to the project dir

12:43 ApeShot: raek: in the checkouts directory, right?

12:43 raek: yes

12:43 ApeShot: raek: or do I need yet another

12:44 raek: ApeShot: in :dependencies, you put whatever you called your private library in its project.clj

12:45 ApeShot: raek: thanks a ton

12:45 raek: all these configuration things are the most frustrating wall between me and hacking

12:45 worth it later to be organized now

12:45 but frustrating now

13:08 jjjjjjj: what's the best way to store data 10 elements long in clojure?

13:08 list or vector?

13:08 ApeShot: jjjjjjj: almost certainly depends on what you do with it

13:08 jjjjjjj: do you want random access or sequential access

13:09 jjjjjjj: generally I will iterate through it at some time

13:09 ApeShot: jjjjjjj: probably with only ten elements it doesn't matter

13:09 jjjjjjj: it does IMO

13:09 ApeShot: jjjjjjj: iteration is fast with lists or vectors

13:09 jjjjjjj: yeah but creation cost is lower with list

13:09 ApeShot: jjjjjjj: are you creating tons of these things?

13:09 jjjjjjj: in an inner loop?

13:09 jjjjjjj: I tried testing this and I think list was like 5 times faster

13:10 ApeShot: jjjjjjj: "vectors" in clojure are functional so conj on a vector should be as fast as cons on a list, I think.

13:10 jjjjjjj: I am not any sort of functional data structures expert, though

13:10 jjjjjjj: or even novice

13:10 jjjjjjj: what is your application?

13:10 jjjjjjj: I know what you're thinking... if you do this once in a program, it doesn't matter right?

13:10 but I use short sequential data all throughout my program

13:11 ApeShot: jjjjjjj: I'm actually thinking, "without more information about his use case, how can he expect me to answer his question meaningfully?"

13:11 jjjjjjj: :D

13:11 gfrlog: you both are missing the obvious answer: A sorted map of finger trees

13:11 ApeShot: golomb forest

13:11 sql database

13:12 jjjjjjj: look it's your basic CRUD app

13:12 ApeShot: what if you need to map reduce on the ten elements


13:12 amalloy: ApeShot: hadoop!

13:12 jjjjjjj: after zeroing down to some unit like a single user or so, you pull related data from DB

13:12 ApeShot: TEN INDEX CARDS

13:13 Hire a grad student to wait around to type them in when needed.

13:13 jjjjjjj: for instance one user has relationship with 5 locations, 3 companies etc

13:13 this is where a bunch of short lists come from

13:13 amalloy: ApeShot: see if you can distribute like seti@home

13:13 ApeShot: jjjjjjj: sorry, we are on a tangent here

13:13 Ptival: ^^

13:13 jjjjjjj: I'm just explaining why most my programs involve creation of bajillion lists of ~10 elements

13:13 ApeShot: jjjjjjj: clojure should make it easy to change the seq type later

13:14 jjjjjjj: If you aren't doing random access, use lists

13:14 jjjjjjj: I was thinking about using transients when filling lists, but it slowed down actually

13:14 ApeShot: a conj should be real cheap

13:14 jjjjjjj: it's not

13:15 ApeShot: anyone know more about this than me?

13:15 Honestly, 95% of the lisp code I write is in Emacs Lisp.

13:15 In EL we have lists and we HAVE TO LIKE IT.

13:15 amalloy: the overhead of creating a transient and then turning it into a persistent is probably larger than the cost of making a list to begin with

13:15 ApeShot: oooo you write EL. plz to fix everything i don't like about clojure-mode

13:16 ApeShot: amalloy: what don't you like

13:16 amalloy: ApeShot: this gets indented wrong: ((juxt + -) 10 <RET> 5)

13:16 ApeShot: amalloy: this is more my kind of thing

13:16 amalloy: https://github.com/VincentToups/emacs-utils/blob/master/README.md

13:17 jjjjjjj: I tried the test of inserting 100000 numbers into short lists of 10 and java kinda outperformed clojure vectors 40 to 1

13:17 ApeShot: jjjjjjj: well, 40/1 isn't bad

13:17 jjjjjjj: did you add type annotations to the clojure code?

13:17 jjjjjjj: sounds bad when that's all your code does :D

13:17 ApeShot: amalloy: the indentation looks ok to me

13:18 amalloy: what would you like it to be like?

13:18 jjjjjjj: annotations? for normal numbers?

13:18 amalloy: ApeShot: 5 should line up with 10, not with (

13:18 as it does for (+ 10<RET>5)

13:18 ApeShot: amalloy: you know, you are right.

13:18 amalloy: ApeShot: i doubt typehints would make a difference when you're just conjing numbers onto a list and not doing any math with them

13:19 ApeShot: amalloy: well, like I said, I'm not really a major clojure guy

13:19 jjjjjjj: however we have a tight loop where another difference maker is i++ vs (inc i)

13:19 fmw: raek: after watching the video, I'm trying to fully understand the code you wrote by writing unit tests for the individual functions. I feel like I'm starting to grok it, but chaining lets like here: http://paste.pocoo.org/show/348510/ feels a bit clunky. Am I doing that optimally, right now?

13:20 amalloy: jjjjjjj: good news: you can use modern computers instead of 1985 mainframes, so the 40:1 difference really won't matter for almost any program

13:20 fmw: I must say that the functional paradigm is awesome while writing tests.

13:21 ApeShot: amalloy: I believe a better name for juxt, incidentally, is "cleave"

13:21 jjjjjjj: amalloy I'm not so sure about that... I had careless "don't look at performance look at ease of programming" bite me in the ass before

13:21 ApeShot: amalloy: If I am not mistaken, it is the equivalent of the concatenative language cleave combinator.

13:22 gfrlog: I had performance issues once. The solution iirc was to remove all the (Thread/sleep ...) statements

13:22 amalloy: jjjjjjj: the programmer's time costs a zillion dollars per hour, and the computer's time is pennies per hour. write it right to begin with, and if you really need the computer to go faster you can improve it

13:22 ApeShot: amalloy: which coincidentally I am adding to my utility library for clojure right now

13:22 amalloy: hah

13:23 fmw: it seems weird to me to see (let [...] (let [...]))

13:23 gfrlog: amalloy: It's a clever way to think about it, but I think for most applications that's not really accurate; e.g., when a user is waiting on something

13:23 ApeShot: amalloy: admittedly, its not clear to me that "cleave" is a more intuitive name than "juxt"

13:23 amalloy: you might as well just (let [... ...])

13:23 jjjjjjj: amalloy...if only it were that simple...one time I had a problem with JSF where page had 3 sec load time with a single user, adding more servers didn't help. Also if you use software like IBM WebSphere portal you pay licenses per CPU power, expensive licenses at that

13:23 so usually customer says...here you have 4 cores, deal with it

13:24 because they have 4 cores worth of licenses for software

13:24 gfrlog: amalloy: tweaking performance is fun!

13:25 and sometimes you get into these situations where the only way to save the princess is to mathematically prove that no algorithm runs faster than your algorithm

13:25 jjjjjjj: :D

13:26 gfrlog: times like those it doesn't matter what's in your inner loop and what's not. Bowser doesn't care.

13:27 fmw: amalloy: ah, like so: http://paste.pocoo.org/show/348518/

13:27 that seems to work

13:30 raek: ok, nevermind bothering you, it was resolved (just letting you know in case you can't see with all the activity in the channel)

13:30 amalloy: thanks :)

13:30 amalloy: fmw: that's a perfectly reasonable change to make to your code but it's not the one i was suggesting

13:30 fmw: amalloy: oh

13:31 what were you suggesting?

13:31 amalloy: i meant (let [stats {...}, new-stats (reduce ...)] ...)

13:31 because let allows multiple bindings

13:31 fmw: amalloy: cool, I didn't know that

13:32 amalloy: $source defn

13:32 sexpbot: defn is http://is.gd/6dmcr0

13:32 amalloy: fmw: ^ is an especially gross use of that fact

13:33 jjjjjjj: doesn't need the comma

13:33 amalloy: jjjjjjj: obviously

13:33 jjjjjjj: just saying...in case fmw doesn't know

13:33 fmw: jjjjjjj: I did know that, but thanks anyway :)

13:33 jjjjjjj: comma is whitespace in clojure

13:33 [1 2 3] is same as [1,2,3]

13:33 fmw: its very safe to assume I don't know that kind of stuff, but in this case I did

13:33 gfrlog: especially if your font is white

13:34 &(doc defn)

13:34 sexpbot: ⟹ "Macro ([name doc-string? attr-map? [params*] body] [name doc-string? attr-map? ([params*] body) + attr-map?]); Same as (def name (fn [params* ] exprs*)) or (def name (fn ([params* ] exprs*)+)) with any doc-string or attrs added to the var metadata"

13:35 gfrlog: amalloy: Do you happen to know why the 'defn' source uses 'def' instead of 'defmacro'?

13:35 amalloy: gfrlog: defmacro doesn't exist yet

13:35 gfrlog: yes but defn is a macro

13:35 so just using (def x (fn [args]...)) shouldn't ... do that

13:35 oh I see the next line

13:35 amalloy: gfrlog: see the end. it alters the var root

13:35 gfrlog: okay very good

13:36 I will start using that in my code everywhere

13:36 amalloy: which is in fact how defmacro works, once it's defined

13:36 gfrlog: ,(.setMacro (var clojure.core/conj))

13:36 clojurebot: nil

13:36 fmw: amalloy: so ^ is not a technical language construct, but its just a let binding the value of that documentation map to to ^?

13:36 gfrlog: ,(conj [] 2)

13:36 clojurebot: java.lang.Exception: Can't take value of a macro: #'clojure.core/conj

13:37 gfrlog: did I just break clojurebot?

13:37 fmw: i.e. not a keyword, just a variable name convention

13:37 amalloy: fmw: *squint* i don't think i understand the question

13:37 gfrlog: ,(cons 7 [])

13:37 clojurebot: (7)

13:37 amalloy: gfrlog: it's not as difficult as you would think

13:37 gfrlog: how does it get unbroken?

13:37 ,(.setMacro (var clojure.core/cons))

13:37 clojurebot: nil

13:38 gfrlog: ,(cons 7 [])

13:38 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (4) passed to: core$cons

13:38 amalloy: gfrlog: hiredman will reboot it, or someone will make these things un-macros

13:38 ,(alter-meta! #'cons assoc :macro false)

13:38 clojurebot: {:macro false, :ns #<Namespace clojure.core>, :name cons, :file "clojure/core.clj", :line 22, :arglists ([x seq]), :doc "Returns a new seq where x is the first element and seq is\n the rest.", :ad...

13:38 amalloy: ,(cons 7 [])

13:38 clojurebot: (7)

13:38 gfrlog: oh okay

13:38 every is dynamic at runtime, I assure myself soothingly

13:39 fmw: amalloy: you were using ^ as an example of let binding multiple values. so from that I can assume that ^ is variable name which is getting assigned that documentation map as a value instead of a language keyword? or well, I guess the concept of a language keyword is different in lisp, because code is data.

13:39 amalloy: uh, i was using ^ as a way to point above me

13:39 to the defn link

13:40 spewn: It's tempting to set alter-meta! to be a macro and yell "Checkmate!"

13:40 gfrlog: I will create a homoiconic language where data is code

13:40 amalloy: spewn: good luck with that

13:40 ,alter-var-root

13:40 clojurebot: #<core$alter_var_root clojure.core$alter_var_root@1c63b78>

13:40 amalloy: there are a lot of ways to change meta

13:41 gfrlog: so...2 ways?

13:41 fliebel: I'd like to see you guys try to break and unbreak clojurebot :)

13:41 amalloy: anyway guys i gotta run. hope that clarified things for you, fmw; ^ is kinda an irc convention

13:41 fmw: amalloy: ok, thanks for the input :)

13:41 amalloy: and it did

13:47 gfrlog: how do I get a new string writer?

13:48 ah nevermind

13:48 jjjjjjj: :)

13:48 (java.io.StringWriter.)

13:48 gfrlog: is there a clojure method for it?

13:48 that's what I found

13:48 jjjjjjj: which is same as (new java.io.StringWriter)

13:49 you can also import classes same as java to make this shorter

13:49 gfrlog: right

13:50 ah well; can't complain

13:53 jjjjjjj: you expected a clojure idiom for making string writer objects?

13:55 gfrlog: no, just something in c.c.duck-streams or something like that

13:55 so (println) respects *out*, but (.printStackTrace e) does not -- that's expected, right?

13:56 is there a clojure function for printing stack traces to *out*?

13:57 jjjjjjj: maybe print stack trace uses System.err not System.out

13:57 different stream

13:57 gfrlog: yes; it doesn't respect *err* either though

13:57 jjjjjjj: ah...

13:57 gfrlog: I would imagine clojure couldn't affect the behavior of that function

13:57 I see a clojure.stacktrace namespace, so I'd bet anybody $15 this will be helpful

13:57 jjjjjjj: you want to print stack trace into a string

13:58 gfrlog: jjjjjjj: no, I want it to go to *out* or *err* -- something I can control

13:58 raek: gfrlog: .printStackTrace has a variant that takes a PrintWriter as an arg

13:58 gfrlog: raek: that sounds like it would work; but would the clojure.stacktrace functions not be preferred?

13:59 jjjjjjj: last resort use (.getStackTrace e) and

13:59 raek: I guess it depends on what you need to do

13:59 jjjjjjj: do whatever you want with it

13:59 gfrlog: jjjjjjjj: that is exactly what I was trying to avoid

13:59 raek: clojure.stacktrace provides functions that know about clojure naming conventions

13:59 gfrlog: jjjjjjj: your name makes it hard to address you directly

13:59 jjjjjjj: how so?

13:59 gfrlog: jjjjjjj: Have to count the j's

14:00 jjjjjjj: :D

14:00 gfrlog: don't you like any other letters? I know a few good ones.

14:00 spewn: gfrlog: No tab completion in your client?

14:00 EDCBA: :)

14:00 gfrlog: spewn: apparently there is

14:00 spewn: many hugs

14:01 EDCBA: I was wondering the same thing

14:01 gfrlog: spewn: what other tricks do I need to learn?

14:01 I'm just going to start complaining about IRC and see what people recommend:

14:01 (am using irssi)

14:01 raek: gfrlog: re you previous question: some java methods print to System.out. rebinding clojure's *out* var does not change it. so yes, that behaviour is expected.

14:02 gfrlog: raek: right - that's what I assume would be different about clojure.stacktrace

14:02 raek: I guess you're thinking that passing *out* to .printStacktrace is easier than :requiring clojure.stacktrace?

14:03 first of all, using a terminal client means I don't get notifications when somebody is talking to me

14:03 second, I don't know how to make passive statements

14:03 third, I don't get as much work done when I'm on IRC

14:04 EDCBA: I think you can change System.out to a stream of your own

14:04 gfrlog: fourth, my three-item-lists always run long

14:04 spewn: gfrlog: "/set beep" will show you some notification-related settings in irssi

14:04 gfrlog: EDCBA: really?

14:04 EDCBA: I don't see why not

14:04 gfrlog: EDCBA: because Java isn't good

14:04 EDCBA: it's not declared final so I assume you can do that

14:05 gfrlog: n

14:06 it even has a .setOut function

14:06 spewn: thanks

14:46 rata_: what's await return value?

14:54 chouser: rata_: nil

14:54 rata_: chouser: thanks =)

15:01 can agents launch programs using c.c.shell-out?

15:04 gfrlog: if I have (defn foo* ...) and (defmacro foo [...] `(foo* ...)), shouldn't the foo* symbol resolve correctly no matter where I call foo from?

15:05 edbond: how to get list of alphabet chars? ["A" "B" ... "Z"] ?

15:05 gfrlog: ,(map str (seq "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))

15:05 clojurebot: ("A" "B" "C" "D" "E" "F" "G" "H" "I" "J" ...)

15:05 gfrlog: that's the best I know of :-/

15:06 rata_: I don't see what else could be the problem here: https://gist.github.com/856670

15:06 raek: ,(map char (range (int \A) (inc (int \Z))))

15:06 clojurebot: (\A \B \C \D \E \F \G \H \I \J ...)

15:07 gfrlog: ,(ruby-eval "[*'A'..'Z']")

15:07 clojurebot: java.lang.Exception: Unable to resolve symbol: ruby-eval in this context

15:07 gfrlog: had to try

15:07 raek: or replace "char" with (comp str char) if you want strings

15:07 Derander: gfrlog: too bad

15:08 gfrlog: Derander: yeah why doesn't clojure include JRuby yet?

15:08 Derander: :-)

15:08 gfrlog: and Jerlang for that matter

15:09 if I have (defn foo* ...) and (defmacro foo [...] `(foo* ...)), shouldn't the foo* symbol resolve correctly no matter where I call foo from?

15:11 rata_: gfrlog: yes, it should

15:11 raek: gfrlog: yes

15:11 gfrlog: stranger and stranger...

15:11 raek: if you have (defn foo* ...) and you are in namespace "user", `foo* should evaluate to the symbol user/foo*

15:12 gfrlog: do you know about macroexpand-1?

15:12 clojurebot: Cool story bro.

15:12 gfrlog: raek: yes

15:12 raek: I'm doing mildly more complicated things, so probably it would all work fine at the repl

15:14 rata_: gfrlog: gist it, maybe we can help you

15:15 gfrlog: rata_: it's not any more complex than what I gave, and indeed it does work at the repl

15:15 I'll have to sort this one out myself

15:16 __name__: hm, i am trying to read the source of persistenthashmap, but it is poorly documented :(

15:16 what does http://bit.ly/evHFJg do?

15:17 Hm, ah.

15:17 0x01f is just 11111.

15:17 raek: __name__: have you seen http://blog.higher-order.net/2009/09/08/understanding-clojures-persistenthashmap-deftwice/ ?

15:17 __name__: raek: yes

15:17 The >>> just confused me. I am no Java guy.

15:18 raek: ah, logical shift right...

15:18 it's interesting that java has both >> and >>>, but C does not

15:22 __name__: Yes, the three > confused me.

15:25 EDCBA: gfrlog I tried that macro

15:25 worked fine for me

15:25 make sure that macro and function are in same namespace

15:52 stupid question but if I want to typehint do I use ^String or #^String

15:52 and how do I typehint primitives

15:54 spewn: EDCBA: As far as I know, you can't typehint primitives because until 1.3, functions can't accept unboxed values. I could be wrong about that though.

15:55 dnolen: EDCBA: in 1.2.0 you can't type hint primitives fn args or return values. You can cast them in let binding and the primitive type information will flow through. You also need to type hint literals.

15:55 (let [x (float 1.0)] ...)

15:55 not also that 1.2.0 since functions can't return primitives you'll need to type hint return values as well.

15:55 (int (+ (int 1) (int 2))

15:55 raek: EDCBA: ^String is the syntax since clojure 1.2. #^String was used in 1.1 and earlier

15:56 dnolen: EDCBA: in 1.3.0 this tediousness is largely eliminated.

16:06 TimMc: The 1.2 compiler accepts primitive type hints, but apparently just ignores them.

16:14 dnolen: TimMc: ignore them in the sense that nothing than can be done in 1.2 w/ that information since in 1.2 functions can only take objects.

16:14 TimMc: But it's forward compatible! :-)

16:15 Mmm, I wonder if ^double effectively results in ^Double or ^Object in 1.2?

16:18 EDCBA: thanks dnolen

16:19 what did you mean about type hinting literals

16:20 dnolen: EDCBA: in 1.2.0, literals are interpreted as their object variants. 1 is Integer not int.

16:20 EDCBA: ah

16:20 so (int ^int 1)?

16:20 dnolen: not

16:20 (int 1)

16:20 EDCBA: yes

16:20 TimMc: ,(int ^int 1)

16:20 clojurebot: Metadata can only be applied to IMetas

16:20 EDCBA: I wasn't aware that (int x) was type hint

16:21 that confused me

16:21 dnolen: EDCBA: it's a cast.

16:21 ^int doesn't mean anything.

16:22 EDCBA: ah

16:22 is there any type casting operation in clojure (for the sake of java interop)

16:26 mrBliss: ,(find-doc "cast")

16:26 clojurebot: -------------------------

16:26 clojure.core/cast

16:26 ([c x])

16:26 Throws a ClassCastException if x is not a c, else returns x.

16:28 raek: EDCBA: when you do an interop call, like (defn matches [^String s] (.matches s)) the bytecode of the clojure fn will have a cast from Object to String

16:29 TimMc: I believe this is equivalent, but less likely: (defn matches [s] (.matches ^String s))

16:30 raek: so casting for the sake of interop is insterted automatically by the compiler for non-reflective method calls

16:30 the class to cast to can be controlled with typehints

16:31 (in some cases, you need to hint an object as an instance of a public interface if the concrete class is a private one)

16:31 (as the compiler would infer the concrete type)

16:35 EDCBA: right

16:35 so if I typehint fn argument then it propagates to calls in that fn

16:36 raek: yes

16:36 EDCBA: what's the purpose of typehints in fn that only call clojure functions?

16:36 I see that sometimes in clojure.core source

16:36 raek: in 1.2, that would be a no-op

16:36 EDCBA: faster clojure interfaces?

16:36 do typehints make interfaces faster?

16:37 another question that's been bugging me for some time, when I use defmulti, I specify dispatch fn. What arguments can that fn expect

16:38 raek: any arguments the user of the multimethod would pass it

16:38 TimMc: Is there a HOF to sequence thunks? Like (foo f g) => (do (f) (g)) ?

16:39 raek: EDCBA: where do you see those typehints?

16:39 EDCBA: I might have been mistaken

16:40 raek: note that core.clj also uses the alternative (. x (method 1 2 3)) syntax instead of (.method x 1 2 3) sometimes

16:40 EDCBA: so if I have multimethod that takes 2 args and I want to dispatch based on first arg's class I need to state #(class %1) as fn?

16:40 raek: that dispatch fn only takes one argument

16:40 you need something like (fn [x _] (class x))

16:41 EDCBA: I can't use reader macro for fn?

16:41 gfrlog: so if the macro doesn't use backticks...and it rewrites using an unqualified symbol...and the macro is called from outside the namespace...how will the symbol be interpreted?

16:41 EDCBA: oh crap I see now

16:41 raek: or (fn [x & _] (class x)) if you want to allow arbitrary number of arguments

16:42 EDCBA: I can't use reader macro because #(class %1) will make a single arg fn

16:42 I see it now

16:42 gfrlog: EDCBA: your nick is hard to type with all the caps. Why not change it to something easy to type and repetitive like jjjjjjj?

16:42 raek: gfrlog: it will be resolved in the context where it is called, which is bad

16:43 gfrlog: raek: okay. thus the default backtick behavior

16:43 raek: where the macro is expanded, not where the macro was defined

16:43 unlike the backtick behavior

16:43 gfrlog: right

16:44 raek: gfrlog: if you do something like (cons 'conj ...) to build the code, you can use (cons `conj ...) instead

16:44 EDCBA: so 'user will become user/user?

16:44 gfrlog: raek: that's a good tip

16:44 EDCBA: gfrlog macros use backtick 90% of the time

16:45 gfrlog: yep

16:45 TimMc: gfrlog: tab-completion is case-insensitive in irssi

16:45 EDCBA: unless you know why you aren't quoting with backtick you shouldn't use normal quote :D

16:45 gfrlog: TimMc: dang

16:45 TimMc: :-)

17:19 raek: Does (fn [x] (boolean (pos? x))) give any benefit in 1.2 over (fn [x] (pos? x)) ?

17:21 raek: TimMc: not that I know of. what would the benefit be?

17:23 TimMc: Wasn't sure if boolean *specifically* acted to annotate the return with type information (besides casting), or whether anything that returns a strict boolean would do that.

17:24 I don't have any reason to believe it does, but I wanted to make sure I wasn't missing something.

17:25 waxrose: Hello every body, I threw together a 1920x1080 clojure wallpaper. Enjoy. :) http://i.imgur.com/n7P9k.jpg

17:27 TimMc: spiffy

17:28 johnmn3: I like it

17:28 waxrose: :D

17:28 TimMc: But a JPG?

17:28 waxrose: Oh, it's in jpg?

17:29 TimMc: I guess imgur changed it.

17:29 waxrose: Yeah, I can put it up on dropbox if you want.

17:29 TimMc: Looks fine, though.

17:30 waxrose: Alright. :)

17:30 TimMc: waxrose: This shall replace my old, uh, "GNU-themed" wallpaper: http://i.imgur.com/88Jgz.jpg :-P

17:30 waxrose: TimMc, haha!

17:30 Epic

17:31 TimMc: (found on Reddit a while ago)

17:31 waxrose: Lol that is awesome.

17:31 * waxrose saves.

17:32 johnmn3: I'd probably wear that fragrance

17:32 TimMc: Contrary to popular opinion, RMS does not actually smell bad in person.

17:32 johnmn3: while chewing my toenails

17:32 waxrose: Real men don't shave.

17:33 TimMc: ...but I think he posed for that picture knowing exactly how it would be used. He's that kind of guy.

17:33 waxrose: lol

17:33 I wish I could meet him in person.

17:33 Him and Sussman.

17:34 amac: sussman seems like he'd be more fun

17:34 stallman is... odd

17:34 waxrose: How so?

17:35 TimMc: I've met RMS once at MIT. He looked just like the pictures.

17:35 amac: I've helped organize conferences where he was a keynote

17:35 waxrose: Lucky.

17:35 amac: look online for a copy of his term sheet

17:35 dfan: rms is a pretty weird guy in real life

17:35 TimMc: Sussman I met at a PL event at Northeastern. He regaled us with tales of making fault tolerant software + hardware for a giant telescope.

17:35 waxrose: I wish I would have gotten my things in order during high school and had applied for MIT in order to meet these guys.

17:36 TimMc: waxrose: How far are you from Boston?

17:36 waxrose: TimMc, I live in Texas.

17:37 dfan: Sussman is actually a reasonable human being

17:37 amac: his video classes for sicp are awesome

17:37 TimMc: I should watch those!

17:37 amac: tres 80's

17:37 dfan: I took SICP in the 80s :)

17:37 amac: nice! it hasn't changed.

17:38 waxrose: TimMc, http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/

17:38 dfan: Has it not? I thought they moved from Scheme to Python or something

17:38 TimMc: waxrose: Yeah, but... not enough time right now.

17:38 waxrose: I was actually given a PERFECT copy of SICP that was published during that time, a couple weeks ago.

17:38 johnmn3: I've been watching those on the metro to work the last few weeks

17:38 amac: that's the nice thing about lisp... its basically been feature-complete for 40 years

17:39 waxrose: dfan, Yeah to Python.

17:39 amac: waxrose: get sussman to sign it

17:39 :)

17:39 waxrose: amac, I have to find him first! haha

17:39 That or get a plane ticket out of Texas.

17:40 dfan: A shame

17:40 amac: I want to get knuth to sign my taocp books

17:40 waxrose: travel is good for you ;)

17:40 TimMc: The reason given for moving to Python was that there was a good robotics package in Python, and they wanted the students to get more experience with both hardware and software.

17:40 waxrose: amac, I hope after I'm done with school I can go find these guys.

17:41 dfan: Huh, I thought they were moving away from the hardware side too

17:41 like the computers we assembled in 6.004

17:41 TimMc: dfan: Oh, huh.

17:42 I really enjoyed Northeastern's Fundamentals of Computer Programming intro course, even though I was a transfer student with a fair amount of Java and functional JS under my belt.

17:42 Fundies is taught in Racket (PLT Scheme).

17:43 dfan: I respect the PLT guys a lot

17:43 TimMc: dfan: Eli is a nutcase, in a good way.

17:43 waxrose: Is the Clojure Conj pretty big?

17:43 amac: where *is* clojureconj?

17:43 TimMc: Matthias scares all his students. :-P

17:44 amac: NC, I think.

17:44 waxrose: amac, Says Durham

17:44 http://www.clojure-conj.org/

17:44 TimMc: I might make it down, escpecially if I get a job at Akamai doing Clojure work.

17:44 waxrose: I wish every thing wasn't so far from Texas.

17:45 dfan: At least everything is equally far from Texas

17:45 waxrose: True.

17:45 I'm actually surprised Austin does not have a Clojure conference of some sort. ( not that I know of)

17:45 amac: I'm in Montreal, getting anywhere in the US costs a fortune.

17:47 TimMc: waxrose: The East and West coasts being everything?

17:49 waxrose: TimMc, Seems like it.

17:49 TimMc: Boston is amazing. I could see staying here a long time.

17:50 dfan: I never left :)

17:50 waxrose: I've lived around the D.C. area before but I've heard that Boston itself is a great place to live.

17:50 TimMc: I'm from Charlottesville, VA.

17:50 Might combine Clojure Conj with a visit to my folks.

17:50 waxrose: And I imagine there are many Lispish type jobs in that area.

17:51 dfan: Every time I travel somewhere warmer during the winter I wonder why I live in Boston

17:51 amac: I'd go to SF over Boston... I've had enough of winters.

17:51 dfan: but then it passes

17:51 TimMc: dfan: I love the snow. :-)

17:51 waxrose: I should save up to go to next years Clojure Conj.

17:52 TimMc, I love the snow as well despite living in TX most of my life.

17:52 amac: TimMc: playing in snow is awesome, living in it sucks ass

17:52 TimMc: waxrose: That's probably why you like it. :-)

17:53 Wow, you apparently can't get from Austin, TX to Durham, NC by Amtrak.

17:53 That, or their website is screwed up as usual.

17:54 waxrose: Ouch.

17:54 Would probably have to go to Dallas instead.

17:55 gfrlog: TimMc: they're pretty bad about connections

17:55 TimMc: gfrlog: I know they can find two-leg routes.

17:55 gfrlog: TimMc: they don't

17:55 TimMc: well sometimes they do.

17:56 TimMc: I travel from CVS to BOS all the time, and used to transfer at NYP or WAS.

17:57 gfrlog: there's a route I would request that involves transferring at WAS, but they won't show it

17:57 waxrose: How is the transportation like there? I'd be great to live some where that does not require a car.

17:57 TimMc: waxrose: I bike to school, 5.5 miles.

17:57 gfrlog: I am not a fan of cars.

17:57 when the cars play, I cheer for the other team.

17:57 unless they are playing trucks

17:57 waxrose: haha

17:58 dfan: Public transportation in Boston is great in theory

17:58 waxrose: TimMc, That is awesome. I wish I could do the same here.

17:58 I actually just paid off my car too.

17:58 TimMc: If you have an ebook reader, public transit probably isn't so bad.

17:58 You'll get a lot of reading done.

17:59 gfrlog: and you probably won't die in a car accident

17:59 or pay thousands of dollars getting anything fixed

17:59 waxrose: TimMc, I work at B&N, so I see my fair share of Nooks.

18:00 gfrlog: Books&Nooks

18:00 TimMc: haha

18:00 You could transfer through... Chicago. -.-

18:00 gfrlog: ,(map #(str % "ooks") ["B" "N"])

18:00 clojurebot: ("Books" "Nooks")

18:02 waxrose: I'm actually waiting for that new Clojure book, The Joy of Clojure to come out.

18:02 Going to grab it from the back of the store as soon as I see it too. ( benefits of working there)

18:03 TimMc: waxrose: http://i.imgur.com/RfACt.png <-- source and destination are both annoying close to major lines.

18:04 waxrose: Wow

18:04 TimMc: I hate our stupid, inadequate ground transit system.

18:04 waxrose: SA is not that far way though thankfully.

18:05 TimMc: You could drive 40 miles to San Antonio, use Amtrak to get to Greensboro, and maybe catch a ride 40 miles to Durham.

18:05 spewn: waxrose: Loving the wallpaper. Could we get a non-JPEG version? And is the background based on anything? It looks familiar.

18:06 gfrlog: Greyhound compared to Amtrak is much better about coverage and routing; much worse about experience

18:06 also cheaper usually

18:06 waxrose: spewn, Sure, imgur changed it to jpg and yes the background was made by, ( forgot source ). All I did was threw the Clojure logo on top and change a couple of image settings.

18:06 TimMc: gfrlog: No power outlets, no room to walk around.

18:06 waxrose: spewn, Would you like the actual background as well?

18:07 spewn: No, I think your composition of the two is great.

18:07 TimMc: waxrose: You wouldn't want to go through Chicago, by the way. The squiggly lines in the WV area mean really slow transit as the train winds through mountains. Gorgeous, but slow as hell.

18:08 (longer distance anyway, of course)

18:08 waxrose: TimMc, Yeah I would much rather go through the southern most route merely because of familiarity.

18:10 gfrlog: TimMc: their newer buses have outlets

18:10 TimMc: gfrlog: That would almost make it bearable.

18:10 waxrose: spewn, http://dl.dropbox.com/u/21959941/clojure-flower-1920_1080.png

18:10 gfrlog: I personally can bear it. But that's only because I have weird ideals.

18:11 I don't think less of people who choose not to

18:11 TimMc: gfrlog: It's not a matter of ideals so much as I can't stand being cooped up.

18:12 I get super fidgety.

18:12 waxrose: I think if I can catch a plane, I would just do it that way.

18:12 gfrlog: TimMc: ah, then you should get the ticket for the fidgety seat

18:13 spewn: waxrose: Merci. Much prettier when the lines are crisp.

18:13 gfrlog: just kidding their tickets have nothing to do with seats

18:13 TimMc: gfrlog: The one with straps? :-(

18:13 waxrose: spewn, You are welcome. :D

18:15 TimMc: waxrose: If you do decide to use Amtrak, make sure to buy a Student Advantage card. You'll more than pay it off on the first trip. (15% off or so on fares.)

18:15 waxrose: Oh wow, thanks for the tip.

18:15 * waxrose writes that down.

18:16 TimMc: You can get other discounts with it, but that's the only one I've found applicable to me. :-P

18:16 waxrose: hehe

18:17 Hopefully by the time I use it I'll have made some Android apps in Clojure. -_-

18:23 TimMc, About how long do you think it would take to get to Durham via amtrak?

18:24 TimMc: waxrose: I already closed the window... but the one-transfer route doesn't run on Nov 9, just on Nov 10 (which is the first day of the Conj). $193.

18:24 Didn't check the length.

18:25 waxrose: Okay thanks. So it would be smart to arrive maybe the 8th then.

18:25 TimMc: SAS -> GRO

18:26 The fuck...

18:26 waxrose: Hmm I probably could go with it being $193. Just would have to find a hotel.

18:26 TimMc: The alternate routes both go through WAS. (DC)

18:26 And Chicago!

18:27 Nov 8 won't cut it, you have to go back to Nov 7.

18:28 That's a redeye: 12:00 Nov 7 -> 16:00 Nov 8

18:28 waxrose: That would at least give me some time to sight see.

18:28 :)

18:28 gfrlog: I had a 4 hr amtrak layover in chicago once. That was when I found out the Sears Tower was not called that anymore.

18:30 waxrose: gfrlog, haha

18:30 TimMc: WAS is a nice layover, if you have little enough luggage to sight-see. I once spent a layover on a cold, rainy day in the Botanical Conservatory, which is basically a huge greenhouse.

18:31 waxrose: TimMc, Thanks a lot for the help. This with the added discount really makes me making it to the Clojure Conj a possibility.

18:31 TimMc: gfrlog: On Greyhound, is there enough seat room to open up a laptop and code?

18:31 waxrose: Yay! (Now I'll feel bad if I don't make it.)

18:32 waxrose: haha

18:32 TimMc: I pretty much spend my entire Amtrak ride programming, or tagging my photos.

18:32 waxrose: I went ahead and put my e-mail in for notification because I know I'll forget.

18:33 devn: hmmm... I'd like to create mock of the twitter stream using clojure. Any suggestions on existing libraries to model a stream like that?

18:34 amac: TimMc: greyhounds are a tight squeeze but doable, the problem is that there are no trays to put the laptop on

18:34 TimMc: amac: Tray for height or keeping your lap cool?

18:35 amac: both

18:35 my laptop gets crazy hot

18:35 gfrlog: TimMc: it's pushing it for sure

18:35 TimMc: Mine doesn't/

18:35 amac: and in tight squeezes the height can be a plus

18:35 gfrlog: TimMc: Another issue is at night you feel like a jerk if the screen is bright

18:35 TimMc: Hmm.

18:35 waxrose: amac, I've never travel via bus long term. How well is the power management for your laptop?

18:36 I assumed they would provide sockets.

18:36 amac: few of the busses have power

18:36 gfrlog: only the new buses

18:36 amac: at least that's the case in canada

18:36 gfrlog: those even have wifi

18:36 I only rode on one once

18:36 TimMc: devn: Are you talking about modeling a producer/consumer architecture, or what?

18:36 amac: I took greyhound from vancouver to ottawa in october last year, and only one bus had power

18:36 gfrlog: ironically that was the same trip that a group of kids brought peeing cats on board

18:37 so the luxury of the newer bus was lost

18:37 devn: TimMc: i want to basically make a fake version of the twitter stream to load test an application im working on

18:37 im wondering how to best achieve that goal

18:37 amac: gfrlog: hah

18:38 devn: the aleph project has a twitter stream api key in their examples

18:38 use that to pump out a dataset

18:39 devn: amac: beautiful

18:39 thanks

19:17 gfrlog: what's the way you can get a stack overflow when using lazy seqs?

19:21 TimMc: gfrlog: I know how to use up memory, but not stack.

19:21 raek: gfrlog: some combinations of reduce and map can cause it

19:22 gfrlog: TimMc: I think it's when you try to print a real long lazy seq

19:22 * raek tries to find an example he saw a while ago

19:22 gfrlog: maybe it's an issue with the c.c.json specifically

19:22 TimMc: Holding onto the head of a lazy seq as you force the contents will eventually use up arbitrarily much memory.

19:22 gfrlog: of course

19:23 TimMc: Oh, you are actually getting a stack overflow in existing code?

19:23 gfrlog: ,(take 14 (clojure.contrib.json/json-str (range 100000)))

19:23 clojurebot: java.lang.RuntimeException: java.lang.ClassNotFoundException: clojure.contrib.json

19:23 gfrlog: TimMc: yeah

19:23 amac: hah, I thought you arbitrarily wanted to break your code

19:24 gfrlog: oh no; not this time

19:24 [[dishes]]

19:25 raek: ,(nth (iterate #(map inc %) [1 2 3]) 10)

19:25 clojurebot: (11 12 13)

19:25 raek: ,(nth (iterate #(map inc %) [1 2 3]) 100)

19:25 clojurebot: (101 102 103)

19:25 raek: ,(nth (iterate #(map inc %) [1 2 3]) 1000)

19:25 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.StackOverflowError>

19:25 raek: ,(nth (iterate #(doall (map inc %)) [1 2 3]) 1000)

19:25 clojurebot: (1001 1002 1003)

19:25 amac: lol

19:25 raek: there

19:25 amac: poor clojurebot

19:25 raek: you end up with somthing like (map f (map f (map f (map f ...))))

19:26 and when the first element out the outermost map is forced, it triggers a cascade of forcings, each one requiring its own stack frame

19:26 amac: though I think you can change the stack size in the java vm if you're ligitimately running out

19:27 raek: gfrlog: so there you have it... that's one way you can get a stack overflow from lazy sequences. :-)

19:27 gfrlog: I had been doing the dishes for a few minutes

19:27 and came to the same conclusion

19:27 and came back to state it

19:28 this is what caused my problem before as well as this time

19:28 I'm hoping (dorun) will make it better

19:28 apparently not

19:28 I should call (vec) I guess?

19:29 raek: gfrlog: doall is sufficient for my example

19:30 it will have the same effect as vec, except that you don't allocate a new data structure

19:31 having a doall in the loop will "flush out the laziness" at each iteration, so that it doesn't build up

19:32 TimMc: I find this surprising.

19:32 I'm going to have to sit awhile and think about how those stack frames build up.

19:33 raek: it's all about where each map step is forced

19:33 TimMc: I think I get it...

19:33 nth forces iterate, but the maps aren't forced until println

19:34 ,((fn [_] nil) (nth (iterate #(map inc %) [1 2 3]) 1000))

19:34 clojurebot: nil

19:34 TimMc: \o/

19:37 Why is def bad for the sandbox? I've seen Scheme eval bots that set up a sandbox where you can define things that last for a while.

19:41 ,(loop [l (list)] (recur (conj l 4)))

19:42 clojurebot: java.lang.Exception: Can't take value of a macro: #'clojure.core/conj

19:42 TimMc: Interesting. Anyway, on my own box that gave me an IndexOutOfBoundsException.

19:43 ,*clojure-version*

19:43 clojurebot: {:major 1, :minor 2, :incremental 0, :qualifier ""}

19:45 waxrose: TimMc, Thanks again for the amtrak info. Time for work so I'll be back on later. See ya!

19:45 TimMc: cheers

19:47 pyr: hi

19:47 I'm having some problems with a specific type of problem in clojure

19:48 i have a recursive function which exits due to stack overflow

19:48 and which would be a good client for loop/recur

19:49 but it calls itselfs more than one through map

19:49 spewn: pyr: Some example code might help.

19:50 TimMc: pyr: Would trampoline help?

19:50 pyr: might

19:50 hold on

19:51 http://pastie.org/1637834

19:52 here goes, a simple path finder which goes through a 5x5 grid

19:52 and finds out unique paths

19:54 i'll look and try to see if trampoline can help me

19:55 TimMc: pyr: By the way, assoc on a vector gives you back a vector. No need for into.

19:56 pyr: true

19:58 TimMc: Are you trying to count the number of unique paths?

19:59 pyr: yep

19:59 amalloy: ,(alter-meta! #'conj assoc :macro false)

19:59 clojurebot: {:macro false, :ns #<Namespace clojure.core>, :name conj, :file "clojure/core.clj", :line 71, :arglists ([coll x] [coll x & xs]), :doc "conj[oin]. Returns a new collection with the xs\n 'added'. (...

19:59 amalloy: ,(loop [l (list)] (recur (conj l 4)))

19:59 clojurebot: java.lang.OutOfMemoryError: Java heap space

20:00 amalloy: TimMc: someone was messing around with breaking clojurebot earlier today and didn't bother to fix him, apparently

20:00 TimMc: hah!

20:00 gfrlog: me?

20:00 * amalloy glares at gfrlog

20:00 clojurebot: your assessment smacks of bias, thus undermining your credibility further. (http://wondermark.com/560/)

20:01 amalloy: i mean, as the co-owner of sexpbot i don't mind seeing clojurebot get beat up on a little, but it's polite to fix him later :P

20:01 gfrlog: I guess I was a little shaken by the experience

20:01 I remember I only macro'd conj and cons I think

20:02 and you un-macro'd one of them?

20:02 amalloy: gfrlog: yeah, it's all fixed up now

20:02 amac: lol

20:02 gfrlog: oh okay. pardon my childishness. Poor bot.

20:02 ,(doc dorun)

20:02 * amalloy pats clojurebot on the head

20:02 clojurebot: "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is co...

20:02 gfrlog: ,(doc doall)

20:02 amalloy: there there

20:02 clojurebot: "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is co...

20:02 gfrlog: dorun and doall are the same?

20:02 amalloy: &(doc dorun)

20:03 sexpbot: ⟹ "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. dorun can be used to force any effects. Walks through the su... http://gist.github.com/856902

20:03 amalloy: &(doc doall)

20:03 sexpbot: ⟹ "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. doall can be used to force any effects. Walks through the su... http://gist.github.com/856903

20:03 gfrlog: these dang bots

20:03 where's printslongstringsbot when you need him?

20:03 spewn: gfrlog: doall returns the head, dorun returns nil

20:03 amalloy: gfrlog: the end of the doc is different but clojurebot truncates

20:03 gfrlog: I'm ignoring the return value

20:03 spewn: Then use dorun.

20:03 gfrlog: and (dorun) didn't fix my problem

20:03 amalloy: sexpbot truncates too of course, but he gists to the rest

20:04 gfrlog: oooh that's what that link is about

20:04 good job sexpbot

20:04 amalloy: yeah, anything that's too long for an irc message

20:04 gfrlog: &(println (vec (range 10000)))

20:04 sexpbot: ⟹ [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 ... failed to gist: Connection reset

20:04 gfrlog: &(println (vec (range 10000)))

20:04 sexpbot: ⟹ [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92... failed to gist: Broken pipe

20:04 amalloy: and that's too long for a gist :P

20:04 gfrlog: oh

20:04 &(println (vec (range 1000)))

20:04 sexpbot: ⟹ [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 ... http://gist.github.com/856904

20:05 amac: ,(= (doc dorun) (doc doall))

20:05 gfrlog: brilliant

20:05 clojurebot: false

20:05 TimMc: ,(doc doc)

20:05 clojurebot: "([name]); Prints documentation for a var or special form given its name"

20:05 amalloy: though in practice there are some things that i didn't bother to plug gisting into, on the assumption that it would never get that long

20:06 spewn: Interesting... in my REPL, (= (doc dorun) (doc doall)) evaluates to true.

20:06 Since each returns nil.

20:06 amalloy: spewn: the bots use special versions of doc

20:06 TimMc: doc prints, ,doc is a bot command

20:06 amalloy: TimMc: no

20:06 TimMc: ,(doc ...) I mean

20:06 clojurebot: Pardon?

20:07 amalloy: ,'anything tells the bot to eval that

20:07 clojurebot: anything

20:07 amalloy: he redefines def to be something that returns a string so that he can capture the output, i imagine

20:07 er, doc

20:07 spewn: ,(meta #'doc)

20:07 clojurebot: {:macro true, :ns #<Namespace clojure.core>, :name doc, :file "clojure/core.clj", :line 3880, :arglists ([name]), :added "1.0", :doc "Prints documentation for a var or special form given its name"}

20:08 TimMc: It must intercept it, then.

20:08 amalloy: &(meta #'doc)

20:08 sexpbot: ⟹ {:macro true, :ns #<Namespace clojure.core>, :name doc, :file "clojure/core.clj", :line 3880, :arglists ([name]), :added "1.0", :doc "Prints documentation for a var or special form given its name"}

20:08 amalloy: sexpbot rebinds it

20:08 TimMc: ,~

20:09 clojurebot: EOF while reading character

20:09 amalloy: the var #'doc still has the same meta, but it resolves to something different because the eval'ed form is wrapped in (binding [doc sexpbot-doc] ...)

20:10 TimMc: ,(conj [] 5)

20:10 clojurebot: java.lang.Exception: Can't take value of a macro: #'clojure.core/conj

20:10 TimMc: ,(alter-meta! #'conj assoc :macro false)

20:10 amalloy: huh. i thought we fixed that

20:10 clojurebot: {:macro false, :ns #<Namespace clojure.core>, :name conj, :file "clojure/core.clj", :line 71, :arglists ([coll x] [coll x & xs]), :doc "conj[oin]. Returns a new collection with the xs\n 'added'. (...

20:10 TimMc: You did. I unfixed it in privmgs.

20:10 *privmsg

20:10 amalloy: okay, that's what i guessed

20:10 TimMc: Turns out there isn't one sandbox per channel/query. That's good to know.

20:11 amalloy: yeah. it's expensive to run a lot of sandboxes

20:11 gfrlog: how does this sandboxing get done? is it a JVM feature?

20:12 amalloy: gfrlog: the jvm sandbox is one facet

20:12 clojail is the library behind sexpbot's sandboxing

20:12 gfrlog: $google jvm sandbox

20:12 sexpbot: First out of 7900 results is: Java's security architecture - JavaWorld

20:12 http://www.javaworld.com/javaworld/jw-08-1997/jw-08-hood.html

20:13 gfrlog: I might find this useful actually...

20:13 amac: ,(map println "abc")

20:13 clojurebot: a

20:13 b

20:13 c

20:13 (nil nil nil)

20:14 amalloy: &(map println "abc")

20:14 sexpbot: ⟹ (abnil cnil nil)

20:14 TimMc: hah!

20:14 amac: hmm... my repl mangles the output of the side effect prints and the return nils

20:14 amalloy: haha, i knew the result would be different but i didn't think it would be that

20:15 amac: yay, I broke something!

20:15 gfrlog: sexpbot: that wasn't very sexp

20:15 amac: clojurebot actually handles that pretty gracefully

20:16 TimMc: &(first (doall (map println "abc")))

20:16 sexpbot: ⟹ a b c nil

20:16 TimMc: &(map println "abc")

20:16 sexpbot: ⟹ (abnil cnil nil)

20:16 TimMc: &(first (map println "abc"))

20:16 sexpbot: ⟹ a nil

20:16 amac: sexpbot's output is what I get at my (slime/swank) repl

20:17 TimMc: amac: That exact string?

20:17 amac: yeah, but with linebreaks

20:17 a b nil c nil nil

20:17 TimMc: ah

20:18 &(map println "abcdef")

20:18 sexpbot: ⟹ (abnil cnil dnil enil fnil nil)

20:18 TimMc: Oh, it is actually quite regular.

20:18 amac: weeeeeird

20:18 TimMc: I mean, I see what it is doing.

20:18 amalloy: TimMc: the behavior there is certainly my fault, though i don't know exactly how :P

20:18 gfrlog: I think it makes sense...

20:18 amac: actuall, not that weird

20:19 just return a's nil last

20:19 gfrlog: ##(println "What's the diff between & and ##?")

20:19 that must be the difference

20:19 one works and the other doesn't

20:19 TimMc: &((constantly "") (map println "abcdef"))

20:19 sexpbot: ⟹ ""

20:20 gfrlog: lazy

20:20 amalloy: gfrlog: the ## at the end is messing up the regex

20:20 ##(println "What's the diff between & and the other thing?")

20:20 sexpbot: ⟹ What's the diff between & and the other thing? nil

20:20 gfrlog: &((constantly "") (doall (map println "abcdef"))

20:20 sexpbot: java.lang.Exception: EOF while reading

20:20 TimMc: OK, there goes that theory... I figured map would eagerly compute the first value.

20:20 gfrlog: &((constantly "") (doall (map println "abcdef")))

20:20 sexpbot: ⟹ a b c d e f ""

20:20 amalloy: the difference is that things like ##((constantly 'this)) work mid-string

20:20 sexpbot: ⟹ this

20:21 gfrlog: amalloy: so what's ## for?

20:21 oh

20:21 you just told me

20:21 amalloy: indeed i did

20:21 gfrlog: you were sitting there waiting for me to see it weren't you?

20:21 amalloy: it is an activity i have grown to enjoy

20:21 gfrlog: with me or with people?

20:22 amalloy: well, i meant you

20:22 amac: amalloy: that's nifty

20:22 amalloy: ## was one of my first contributions to sexpbot

20:22 gfrlog: why does the regex mess up my original string?

20:23 amac: tries to parse the end of the print statement as another expr

20:23 amalloy: righto

20:23 gfrlog: I'd like to see the regex

20:23 amalloy: gfrlog: no you wouldn't :P

20:23 it's horrible

20:23 amac: hahaha

20:23 there's no such thing as a nice regex

20:24 gfrlog: couldn't you just use (read-string) or some such thing after any "##"?

20:24 amalloy: "##(([^#]|#(?!#))+)\s*((##)?(?=.*##)|$)"

20:24 gfrlog: ,(doc read-string)

20:24 spewn: That's hardly horrible...

20:24 clojurebot: "([s]); Reads one object from the string s"

20:24 amalloy: gfrlog: that would probably be best

20:24 but i wanted to make it possible to end a ## section with another ## and go back to talking normally

20:25 gfrlog: that would take care of the nested parentheses that regular expressions are not powerful enough for...

20:25 amalloy: gfrlog: it does use read-string eventually

20:25 gfrlog: so that's why it ##'ignores what's after the first ## but before another

20:25 sexpbot: ⟹ ignores

20:26 amalloy: if you commit an improvement to use read-string more sensible i'll pull it in :P

20:26 gfrlog: okay, which file was that in?

20:26 amalloy: gfrlog: the regex is in .sexpbot/info.clj

20:26 it gets used in src/sexpbot/plugins/clojure.clj

20:26 TimMc: How does git collaboration via pull work anyway? Do I just fork, commit, push, and make a pull request?

20:26 amalloy: TimMc: yep

20:27 amac: I'm really curious how clojurebot is getting proper formatting on that ugly map

20:27 gfrlog: I've done that once and got rebuked for it

20:27 amalloy: clojurebot: source?

20:27 clojurebot: source is http://github.com/hiredman/clojurebot/tree/master

20:27 TimMc: And the recipient chooses which branch to target?

20:27 amalloy: TimMc: yeah

20:27 TimMc: That's not very scary at all!

20:27 amalloy: gfrlog: well, you might want to see whether the owner is looking for collaborations, but it seems weird for anyone to get annoyed about a pull request

20:28 gfrlog: amalloy: I was fixing a typo in a doc; owner said pull request was too much trouble for such a thing and I should send him a message

20:28 amalloy: eg clojure.core doesn't accept pull requests if you haven't signed a contributor agreement, but i can't see anyone being mad about it

20:28 gfrlog: he's just dumb. pull requests are mad simple

20:28 gfrlog: yeah we hate him

20:29 amalloy: if you want to go egg his house or something, sign me up

20:29 gfrlog: just realized he's the owner of a prominent clojure project that I like

20:30 amalloy: haha

20:30 well don't tell me who

20:30 gfrlog: nope

20:30 I'm too grownup for that

20:30 not grownup enough to have forgotten it by now

20:31 I'll quote his message though: "Its far easier for me just to add the missing char then to pull your branch, merge it, repush etc. For larger patches, pulls are preferred."

20:33 TimMc: Urgh, I don't want to print out a form, fill it out, and mail it.

20:33 gfrlog: TimMc: and that's why I'm not a contributor either

20:33 amalloy: TimMc: yeah, it's a pain, but c'est la vie. i sent mine in eventually

20:33 amac: like... on paper?

20:33 how passe

20:34 TimMc: amac: and a stamp and everything!

20:34 gfrlog: I don't own a printer, a pen, or a postal service

20:34 TimMc: amac: You even have to write out your email address longhand!

20:34 gfrlog: in cursive

20:34 amac: that just seems so... wrong

20:34 gfrlog: I've long forgotten how to do a cursive '@'

20:35 amalloy: gfrlog: they probably teach that in elementary schools now

20:35 amac: wonder why its not an online form, I'm fairly sure its still legally binding

20:35 amalloy: the internet makes the @ so much more important

20:36 gfrlog: amalloy: my son ain't lurnin no at-sine

20:36 amalloy: amac: rich is a closet luddite

20:36 amac: hahahaha

20:37 TimMc: Or his attorney is. :-)

20:37 gfrlog: he writes code with a hammock instead of a build tool

20:38 amalloy: does the ## apply to all of sexpbot, or just the clojure plugin?

20:38 * TimMc creates account "amallloy" on GitHub so he can sneak contributions in

20:38 amalloy: just clojure

20:38 TimMc: good luck with that

20:39 gfrlog: there's an "embed" plugin that's supposed to allow something like $#command#$ but i don't think it works

20:40 amac: &(battle 'clojurebot)

20:40 sexpbot: java.lang.Exception: Unable to resolve symbol: battle in this context

20:40 gfrlog: I think I'm finding it

20:40 amalloy: This whole repo has plenty of test coverage, right?

20:40 amalloy: hahaha

20:40 no not at all

20:41 clojail has decent testing because it might actually be bad if that broke

20:41 amac: ,(kill 'sexpbot)

20:41 clojurebot: java.lang.Exception: Unable to resolve symbol: kill in this context

20:41 amalloy: but i wrote all of those tests, and Raynes is too lazy to write any for sexpbot

20:41 gfrlog: clojail doesn't have any mechanism for loading code in a sandboxed way does it?

20:41 * TimMc alters the CCA before printing and mailing it to say "However, TimMc is exempt from all above conditions."

20:41 amac: one of these days they'll start fighting, I know it

20:41 amalloy: gfrlog: that's practically what clojail *is*

20:42 gfrlog: amalloy: I don't mean just evalling, I mean vars and namespaces and all

20:42 amac: TimMc: funny enough, no one would probably notice

20:42 :)

20:42 gfrlog: e.g., two sandboxed threads with two different root bindings for the same var

20:43 amalloy: gfrlog: no, but you can start another clojail process from the command line :P

20:44 gfrlog: I wonder if rebinding def would be an effective way of doing it...

20:44 amalloy: def is a special form

20:44 gfrlog: dackbutton

20:44 it's not *that* special

20:45 ,(let [def 12] (+ 5 def 83 3))

20:45 clojurebot: DENIED

20:45 gfrlog: &&(let [def 12] (+ 5 def))

20:45 sexpbot: java.lang.Exception: Unable to resolve symbol: & in this context

20:45 gfrlog: &(let [def 12] (+ 5 def))

20:45 sexpbot: java.lang.SecurityException: You tripped the alarm! def is bad!

20:45 gfrlog: I suck at bots

20:45 amalloy: &(let [if 10 do 20] (do if))

20:45 sexpbot: ⟹ 10

20:46 gfrlog: you've done that before

20:47 TimMc: &(let [a 4 def 5] (+ a def))

20:47 sexpbot: java.lang.SecurityException: You tripped the alarm! def is bad!

20:47 amalloy: gfrlog: and yet, every time it's still funny

20:47 gfrlog: amalloy: that's exactly the point I was making

20:49 TimMc: I find the patents section of the CCA unreadable.

20:49 Also, is "Clojure" the project name?

20:49 amalloy: yeah

20:50 TimMc: And I use my GitHub username?

20:50 Maybe I will remember to print this at school on Monday.

20:51 amac: I find most legalese unreadable

20:51 amalloy: i thought the CA was pretty readable

20:51 amac: my brain can't be bothered to parse that shit, I just stare at the paper

20:51 TimMc: I'm pretty good at reading legalese, but I'm unsure of how to interpret "with respect to" in 3.

20:52 Needs parens.

20:52 * amalloy doesn't plan to reopen the CA in order to participate meaningfully in this discussion

20:54 * TimMc helpfully pastes the entire thing into the channel

21:13 gfrlog: $google polyomino tiler

21:13 sexpbot: First out of 1850 results is: Sandbox: Polyomino Tiler

21:13 http://gfredericks.com/sandbox/polyominoes

21:15 amac: gfrlog: that's pretty neat

21:17 gfrlog: what algorithm does it use for packing?

21:19 gfrlog: oh

21:19 um

21:19 lessee

21:20 it tries everything by backtracking; just about all of the algorithmic details are how it chooses which square to try to tile next

21:21 amac: been a while since i've looked at knapsack/bin packing algorithms... something I should brush up on

21:21 gfrlog: every step of the algorithm is displayed visually

21:21 I just did it as a bipartite graph, by pre-generating all possible placements

21:22 not feasible for real big grids, but works for this

21:22 it's much easier after that too, because I didn't have to think about directions or squares anymore; just graph algorithms

21:23 amac: do you memoize some common open paterns to fill?

21:24 gfrlog: no; I've thought of that; more I've thought of memoizing unfillable spaces

21:24 amac: would probably speed things up considerably

21:24 gfrlog: maybe

21:25 there would be a lot of combinations....

21:25 have to be careful about memory

21:25 amac: true, but easy to address if you keep the common fillable/unfillable spaces small

21:25 then just stack those together to get approximate fillings, then backtrace the rest

21:26 gfrlog: I'm skeptical...I think there's more promise in looking at the parity of different pieces

21:26 at least in certain situations

21:27 how would you generate these common fillable spaces?

21:29 amac: generate a bunch of randomly populated maps and parse out the open spaces, sort by the number of times the patterns appear in your dataset, then run your packer on them and label them as fillable/unfillable

21:30 gfrlog: oh, are you using the "Random Grid" button?

21:30 amac: I filled mine in by hand

21:31 but randomizing the grid would give you a set of commonly occuring patterns

21:31 gfrlog: I guess I'm thinking that the 'common spaces' wouldn't come up very often

21:31 and they'd be specific to a set of polyominoes

21:32 so just by that any kind of pre-generation of the data would be implausible

21:32 amac: I guess it depends on how big the empty spaces are

21:32 gfrlog: since the app allows any arbitrary set of polyominoes

21:32 amac: ...there's a reason this is np-hard ;)

21:32 gfrlog: is it?

21:32 amac: yeah, I'm fairly sure

21:33 gfrlog: of course NP-hard is just worst case

21:33 the algorithm works quite well in a lot of cases

21:33 amalloy: i don't remember who was asking about this a while ago, but apparently clojure.lang.Compiler/specials is a map of all the compiler-level special forms

21:34 gfrlog: ,clojure.lang.Compiler/specials

21:34 clojurebot: {deftype* #<DeftypeParser clojure.lang.Compiler$NewInstanceExpr$DeftypeParser@257ce0>, new #<Parser clojure.lang.Compiler$NewExpr$Parser@1bf0f5b>, quote #<Parser clojure.lang.Compiler$ConstantExpr$Pa...

21:34 gfrlog: ,(keys clojure.lang.Compiler./specials)

21:34 clojurebot: java.lang.ClassNotFoundException: clojure.lang.Compiler.

21:34 amac: tell me more, clojurebot!

21:34 amalloy: gfrlog: c'mon, remember the gisting

21:34 &clojure.lang.Compiler/specials

21:34 sexpbot: ⟹ {deftype* #<DeftypeParser clojure.lang.Compiler$NewInstanceExpr$DeftypeParser@1676e67>, new #<Parser clojure.lang.Compiler$NewExpr$Parser@1822dc7>, quote #<Parser clojure.lang.Compiler$ConstantExpr$Parser@e417de>, & nil, var #<Parser clojure.lang.Compiler$TheVarExpr$... http://gist.github.com/856970

21:35 gfrlog: amalloy: I'm an old man. I've been using clojurebot for most of my life. I can't just switch because it's a good idea.

21:35 amac: haha

21:36 also, commas are much sexier punctuation

21:36 gfrlog: ,(keys clojure.lang.Compiler/specials)

21:36 clojurebot: (deftype* new quote & var set! monitor-enter recur . case* ...)

21:36 gfrlog: augh

21:36 amalloy: BAM!


21:36 somebody take his gun

21:38 TimMc: Why is one of my sexprs in Emacs suddenly bright red?

21:38 clojurebot: emacs is best configured for Clojure with instructions at http://technomancy.us/126

21:38 amalloy: TimMc: it's embarrassed

21:39 gfrlog: amac: I'm about to rewrite that algorithm in clojure, sorta

21:39 amac: gfrlog: pastebin it

21:40 :)

21:40 gfrlog: amac: in a month or two, sure

21:40 TimMc: It compiles, though.

21:41 gfrlog: ,(println "&(println \"Hey clojurebot\")")

21:41 clojurebot: &(println "Hey clojurebot")

21:41 sexpbot: ⟹ Hey clojurebot nil

21:42 gfrlog: oh now I need to look up how to do quines in clojure

21:42 amalloy: gfrlog: you won't be able to make it work

21:42 amac: holy shit they're talking to each other!

21:42 gfrlog: amalloy: why not?

21:42 I'll have to invent some kind of trampoline-quine...

21:43 TimMc: amalloy: Eli got a loop going between several bots in #scheme at one point.

21:43 amalloy: irc doesn't send you back your own messages, so you can't self-quine. you can't co-quine because sexpbot prefaces everything with ⟹

21:43 amac: ok, we've gotta do this

21:43 and let them fight to the death

21:44 TimMc: amalloy: And the bots ignore each other, right? Right?

21:44 amalloy: TimMc: of course not. didn't you just see the counterexample?

21:44 gfrlog: &(println ",(println \"Hey sexpboty\")")

21:44 sexpbot: ⟹ ,(println "Hey sexpboty") nil

21:44 gfrlog: get hiredman to add ## to clojurebot

21:44 TimMc: amalloy: Oh! Misread.

21:45 amalloy: heh

21:45 gfrlog: does sexpbot preface for ##(println "as well?")

21:45 sexpbot: ⟹ as well? nil

21:45 gfrlog: dorn

21:45 s/o/a

21:45 sexpbot: <gfrlog> darn

21:46 amalloy: clojurebot might actually have sexpbot on ignore anyway

21:46 $login

21:46 sexpbot: You've been logged in.

21:46 amalloy: $say #clojure ,1

21:46 sexpbot: ,1

21:46 clojurebot: 1

21:46 amalloy: $logout

21:46 sexpbot: You've been logged out.

21:46 gfrlog: holy crap it's like he just stepped through a wall or something

21:47 amalloy: ?

21:47 gfrlog: your $login trick

21:47 it was very sexp

21:47 amalloy: *chuckle*

21:47 amac: &(println ",(+ 1 2)")

21:47 sexpbot: ⟹ ,(+ 1 2) nil

21:48 amac: stupid arrow

21:48 gfrlog: log back in and turn off the arrow

21:48 amalloy: gfrlog: that's actually hardcoded

21:48 gfrlog: everything is dynamic at runtime

21:48 rebind some vars, come on!

21:48 TimMc: gfrlog: Ha!

21:48 $say $clojure hello

21:48 sexpbot: TimMc: It is not the case that you don't not unhave insufficient privileges to do this.

21:49 TimMc: Ah, OK.

21:49 And I mistyped anyway.

21:49 amalloy_: $login

21:49 amac: lol

21:49 gfrlog: had to try

21:49 amalloy: gfrlog: wouldn't work even if i let you have my nick

21:49 you'd need my IP too

21:50 amac: that can be spoofed, as long as the response isn't necessary

21:50 amalloy: amac: yeah

21:50 gfrlog: which it isn't...

21:51 well

21:51 maybe it is who knows

21:51 amac: probably not

21:51 amalloy: probly not

21:51 gfrlog: dang layers upon layers of networking protocols

21:51 doesn't it use TCP?

21:51 3-step handshake?

21:52 TimMc: You can spoof a single packet, and that's about it.

21:52 gfrlog: come on guys, it's completely inconceivable that anybody could be writing clojure code and not have come up through a normal CS department with a required networking course, right?

21:52 * amalloy waits for gfrlog to spoonfeed us all whatever point he's making

21:53 amac: you underestimate my ability to skip class

21:53 gfrlog: hmm

21:53 I think I was making a joke rather than a point

21:53 amalloy: yeah, but it sounded like a joke about your inability to get a point across

21:53 gfrlog: I'm not very good at jokes

21:54 I take a shotgun approach

21:54 TimMc: brb, need to pour alginate on my housemate

21:55 amac: TimMc: don't we all.

22:07 TimMc: sexpbot: commands?

22:07 Bah, nevermind.

22:07 It's in my history,

22:08 amalloy: speaking of which, if anyone wants to get their feet wet writing for sexpbot, he could use a commands? function :P

22:08 amac: &(learn 'commands)

22:08 sexpbot: java.lang.Exception: Unable to resolve symbol: learn in this context

22:08 amac: I tried

22:10 amalloy: good effort

22:11 TimMc: sexpbot: mail clojurebot ,1

22:11 sexpbot: Message saved.

22:11 TimMc: clojurebot: hi

22:11 clojurebot: I don't understand.

22:11 amalloy: TimMc: interesting attack vector

22:11 TimMc: Does it use privmsg?

22:11 amalloy: yeah

22:12 TimMc: bah

22:12 Also, switching to visual bell. These speakers are turned up too high. >_<

22:13 amalloy: I've also considering using the title of a dynamic page on a site I control.

22:15 clojurebot: ,(println "s/I/,'")

22:15 clojurebot: ,(println "clojure bot is the best!")

22:15 TimMc: what

22:15 amalloy: *blink*

22:16 amac: it's... alive

22:16 amalloy: oh

22:16 TimMc: what the shit

22:16 amalloy: comma only triggers eval if it's the very first char

22:16 this was his canned response to some factoid

22:17 amac: doesn't he also just respond randomly to a small percentage of messages?

22:18 clojurebot: ,(println "s/I,'")

22:18 clojurebot: ,(println "clojure is the best")

22:18 amac: scratch that, its reproducable

22:19 er, almost

22:20 spewn: clojurebot: println

22:20 clojurebot: ,(println "clojure bot is the best!")

22:21 TimMc: clojurebot: setup

22:21 clojurebot: simple setup is http://www.thelastcitadel.com/dirt-simple-clojure

22:21 TimMc: ,(println "s/.*/,1")

22:21 clojurebot: s/.*/,1

22:21 sexpbot: <clojurebot> ,1,1

22:22 TimMc: Oh, right.

22:35 amac: ,(do (println "#*(println \"stuck\"") (println "s/*/#))

22:35 clojurebot: EOF while reading string

22:38 amac: ,(do (println "#*(println \"stuck\")") (println "s/*/#"))

22:38 clojurebot: #*(println "stuck")

22:38 s/*/#

22:39 spewn: Turns out that double replacement there is not a bug in sexpbot.

22:40 ,(.replaceAll "foobar" ".*" "baz")

22:40 clojurebot: "bazbaz"

22:40 spewn: Does that look weird to anyone else?

22:41 johnmn3: were you expecting "baz" ?

22:41 spewn: I was.

22:42 ,(.replaceAll "foobar" "^.*" "baz")

22:42 clojurebot: "baz"

22:42 mec: thats really weird

22:42 spewn: I would expect .* to match the entire string regardless of the anchor there.

22:42 johnmn3: I dunno. "All" might seem strange otherwise

22:43 spewn: ,(.replaceFirst "foobar" ".*" "baz")

22:43 clojurebot: "baz"

22:43 spewn: What's the second?

22:44 johnmn3: hmm. * grabs the whole string that time

22:44 spewn: As it always should.

22:45 ,(.replaceAll "foobar" ".*?" "baz")

22:45 clojurebot: "bazfbazobazobazbbazabazrbaz"

22:45 spewn: Nongreedy finds all zero-width spots, I see.

22:51 amalloy: .* matches the whole string once, and then the zero-width spot after the end of the string

22:52 youcould use .+

22:54 dfan: Is there a way to do quot and rem simultaneously?

22:54 amalloy: juxt

22:54 &((juxt quot rem) 10 3)

22:54 sexpbot: ⟹ [3 1]

22:55 dfan: OK, but that doesn't actually save any time, right?

22:55 amalloy: right

22:55 dfan: OK, thanks

22:56 TimMc: The JVM might not provide a divmod operator.

22:56 (even though it is available on most ISAs)

22:58 spewn: amalloy: It looks to me like it's the zero-width spot at the beginning that gets matched as well as the entire string, since the behaviour changes with ^.*

22:58 But why?

22:59 amalloy: spewn: huh? ^ would change my imagined behavior too

22:59 &(re-seq #".*" "test")

22:59 sexpbot: ⟹ ("test" "")

22:59 spewn: Oh, silly of me. Of course it would.

22:59 TimMc: I consider it broken.

22:59 amalloy: and arguably wouldn't change yours

23:00 TimMc: then you're not thinking hard enough. this is exactly the behavior you can derive from the definition of *

23:00 TimMc: Isn't * greedy by default?

23:00 amalloy: uh huh...

23:02 TimMc: What am I missing?

23:02 I use regex *all the time*.

23:03 ,(.replaceAll "foobar" ".*" "12")

23:03 clojurebot: "1212"

23:03 spewn: TimMc: .* matches up until the last character, but does not include the zero-width spot after the last character. Then .* matches the zero-width spot after the last character.

23:04 TimMc: That's...

23:05 OK, I think I can accept that. Maybe.

23:05 spewn: Assuming my understanding so far is correct, I guess what I'm confused about is why the first match doesn't match the zero-width spot at the end. I suppose it's because it stops looking when it runs out of characters.

23:05 TimMc: I suppose the semantics for replace are tricky.

23:05 Replace involves restarting the matching, but match doesn't.

23:06 s/.+/s\/.+\/,1\//

23:07 ,(use '[clojure.contrib.bot-quine])

23:07 clojurebot: java.io.FileNotFoundException: Could not locate clojure/contrib/bot_quine__init.class or clojure/contrib/bot_quine.clj on classpath:

23:12 * amalloy is reading On Lisp and rediscovering his gratitude that clojure defaults to hygenic macros

23:14 TimMc: It does?

23:15 Ah, nvm.

23:15 amalloy: and i even recently went through some gyrations to create an unhygenic macro on purpose. even so, i'm glad it's hard :P

23:17 joshua___: thunk, your a fellow clojurian! Excellent!

23:17 thunk: Ahoy! I mostly lurk here

23:17 amac: everyone mostly lurks here

23:18 :)

23:19 TimMc: Can the core collections be safely serialized and restored?

23:21 amalloy: TimMc: pr, read-string?

23:21 TimMc: pr... nice

23:23 amalloy: indeed, it's clever enough that if it were my original idea i'd be proud of it

23:23 amac: ,(doc pr)

23:23 clojurebot: "([] [x] [x & more]); Prints the object(s) to the output stream that is the current value of *out*. Prints the object(s), separated by spaces if there is more than one. By default, pr and prn print i...

23:24 amac: handy.

23:25 TimMc: amalloy: ...but it won't work here. There are Java objects in the collection.

23:25 amalloy: print-dup

23:25 TimMc: No docstring!

23:25 amac: ,(doc print-dup)

23:25 clojurebot: "; "

23:25 amac: booooooo

23:26 ,(source print-dup)

23:26 clojurebot: java.lang.Exception: Unable to resolve symbol: source in this context

23:26 amalloy: if the java classes you'll need to deal with are a closed set, you can implement print-dup for them

23:26 it's a multimethod for printing readable strings

23:26 TimMc: Oh, sweet.

23:27 Is there a read-dup?

23:27 (There isn't by that name.)

23:27 amalloy: TimMc: it's called read-string

23:27 &(print-dup *ns*)

23:27 sexpbot: java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$fn--3893$fn

23:27 amalloy: &(print-dup *out* *ns*)

23:27 sexpbot: java.lang.IllegalArgumentException: No method in multimethod 'print-dup' for dispatch value: class java.io.StringWriter

23:27 amalloy: &(print-dup *ns* *out*)

23:27 sexpbot: ⟹ #=(find-ns sandbox11264)nil

23:28 TimMc: So, I should print the Java objects as calls to their constructors?

23:28 amalloy: yeah

23:28 TimMc: Nice.

23:28 amalloy: TimMc: when the compiler sees a #=(...) form it evaluates the code and uses it in place of the original #= form

23:29 the bots don't allow it, but try it in your repl

23:30 TimMc: I'm entirely sure that is not documented on http://clojure.org/reader

23:30 amalloy: yeah, it's hard to find

23:30 $google clojure print-dup

23:30 sexpbot: First out of 1150 results is: Serializing Clojure data structures - Lisp - Snipplr Social ...

23:30 http://snipplr.com/view/13559/serializing-clojure-data-structures/

23:39 TimMc: whee

23:45 skelternet: (doc print-dup) gave me a bunch o'nils

23:45 clojurebot: "; "

23:46 TimMc: skelternet: It's a multimethod you implement. Check the source. :-/

23:47 amalloy: you're not a real OSS developer until you tell someone to read the source :P

23:47 TimMc: I said it with a chagrined emoticon!

23:48 amalloy: i don't think that makes it unhappen

23:48 i'm sorry TimMc, there's just no avoiding it...you're a nerd now

23:48 TimMc: Haw, that happened a while ago.

23:49 skelternet: The ability to "serialize" a clojure data (sequence?) directly, and load it later, in clojure syntax, instead of using json, xml, is of interest to me.

23:50 amalloy: skelternet: i'd say structure instead of sequence, just because it's more generic

23:51 but yeah, that's one of lisp's strengths

23:52 skelternet: it seems under-represented

23:52 amalloy: skelternet: it's a direct consequence of the syntax being so minimal

23:52 skelternet: or I'm not googling for the right things

23:52 amalloy: heh

23:53 dang, i have a favorite article about this subject but i can't remember where it is

23:53 skelternet: I'd love to read it

23:54 TimMc: amalloy: Happen to know offhand if the Clojure reader supports circular data structures using the sharp syntax?

23:54 #3#, etc.

23:54 amalloy: TimMc: yes; no

23:55 TimMc: OK

23:55 amalloy: aha! skelternet: http://www.defmacro.org/ramblings/lisp.html

23:56 it's only somewhat topical but still interesting

23:57 skelternet: thank you!

23:57 amalloy: it's really hard to google for "sexprs are like xml but not awful"

23:57 because pretty much everyone says that

23:57 skelternet: :)

23:59 pdk: nah

23:59 i think they just say the xml is awful part

23:59 at least outside of our little circles

23:59 amalloy: pdk: outside our little circles everyone says xml is awesome

Logging service provided by n01se.net