#clojure logs

2011-03-06

00:00skelternetthe documentation to write and parse xml in clojure is easier to find than the reason not to, and how to dump your struct to a clojure file, and read it back in.
00:01skelternetSure the clojure docs are there, but I haven't found a blog or an article that says "no no, don't do that...do this! It's native!"
00:01amalloyskelternet: if your struct doesn't include foreign java objects, the latter is trivial and the former is not
00:02amalloybut send an email to alan@malloys.org to remind me and i'll see if i can put together a blog post about it
00:02TimMcOh, this is bloody brilliant.
00:02amalloyTimMc: the article, or something you've just done?
00:03TimMcThe serialization support.
00:03skelternet?
00:03TimMcskelternet: Let me gist something for you.
00:03amalloyi think he's referring to the extensibility of print-dup
00:04skelternetI'm so new, I don't think I could ref my own butt at this point.
00:04skelternetHowever, I did manage to use enlive to rescue our database schema documentation from our wiki. 3500 column defs
00:04amalloyhah
00:05skelternetso, now is a good time for me to sharpen my saw.
00:05skelternet(only 3500 of the columns were documented. we have >6000)
00:06TimMcamalloy: OK, less brilliant than I thought.
00:06amalloylol
00:06amalloyTimMc: gist it already
00:09TimMchttps://gist.github.com/857048
00:10skelternetoops
00:10amalloy$google defrecord2
00:10sexpbotFirst out of 20 results is: david-mcneil/defrecord2 - GitHub
00:10sexpbothttps://github.com/david-mcneil/defrecord2
00:10amalloyi believe that includes readable print-dups
00:10TimMcheh
00:14TimMcThanks, I'll think about using that.
00:14skelternetit seems long. but yeah, thank you!
00:15TimMcFor now, though... bed. G'night!
00:32waxroseHowdy every one. :)
00:34amalloyhola waxrose
00:34waxroseamalloy, :D
01:49Scriptorman, not seeing pipes to separate stuff in the topic feels weird
01:50amalloysilly Scriptor, pipes are for combining stuff! find | grep
01:51Scriptorbut...but...delimeters!
02:28amalloyheehee. i just wrote (str tok). reminds me of the bad old days in C
02:33Deranderamalloy: I have never written a C program
02:34amalloyDerander: it's not a bad thing to be able to do
02:34amalloywhat are your other languages?
02:34shachafamalloy: Hopefully not with the same meaning as in C? :-)
02:34Deranderamalloy: the web languages
02:34Deranderamalloy: javascript, php, ruby, clojure
02:34DeranderI guess I know haskell
02:34amalloyDerander: the joke is that strtok is one of C's worst APIs
02:35amalloyit's inherently un-thread-safe
02:35shachafClojure is a web language?
02:35DeranderI know that string stuff in C is the cause of problems
02:35Deranderscode_: no.
02:35Deranderscode_: wrong person, sorry. shachaf
02:35DeranderI just meant that I came into programming primarily through the web
02:35amalloyDerander: strtok is worse. iirc instead of returning something, it modifies a global variable to reflect what it wants to return
02:35Deranderbrilliant
02:36amalloy$google c strtok string.h
02:36sexpbotFirst out of 7770 results is: strtok - C++ Reference
02:36shachafTo be fair, there's strtok_r.
02:36sexpbothttp://www.cplusplus.com/reference/clibrary/cstring/strtok/
02:36amalloyshachaf: sure sure
02:37shachafamalloy: Is strtok *inherently* thread-unsafe?
02:38Deranderamalloy: I guess I was being vaguely untruthful. C was the first language I "learned", but I was 6-7 at the time and it did not stick.
02:38amalloyshachaf: C string to truncate. The contents of this string are modified and broken into smaller strings (tokens). Alternativelly, a null pointer may be specified, in which case the function continues scanning where a previous successful call to the function ended.
02:39amalloyso to get more than one token out of your string, you call it with NULL after the first time
02:39shachafamalloy: Sure, but it could use a thread-local variable instead of a global variable pretty easily.
02:39amalloythat's fair, i suppose
02:39amalloyyou still have to add the _r semantics to be any good at all, of course
02:40shachafOf course.
02:40shachafAnd even then it's a pretty suspicious function.
02:41amalloywhereas (str tok) is delightfully clear and simple: convert tok to a string :P
03:07amalloyguys fnparse is pretty awesome
03:20khaliGhi, what's the idiomatic way of getting the filenames in a directory?
03:21amalloykhaliG: file-seq, i think
03:21khaliGamalloy, looks good, thank you
04:59octe,(/ 10 3)
04:59clojurebot10/3
05:04clgv,(/ 30 9)
05:04clojurebot10/3
05:04clgvjust curious^^
05:19bennylutwhat functions can iterate over a map (as key-value pairs)?
05:20clgve.g. map ;)
05:20clgvafaik a map is a seq of key-value pairs
05:20bennylutclgv, hmm.. didnt know it can be handled like that
05:21bennylutthe map function parameter just need to get 2 parameters (aka key+value)?
05:21clgv&(map #(println (str "key = " (key %) " val = " (val %))) {:bla 1 :blubb 2.0 :lala 10/3})
05:21sexpbot⟹ (key = :bla val = 1key = :blubb val = 2.0nil key = :lala val = 10/3nil nil)
05:22bennylutclgv, thanks!\
05:22clgv&(dorun (map #(println (str "key = " (key %) " val = " (val %))) {:bla 1 :blubb 2.0 :lala 10/3}))
05:22sexpbot⟹ key = :bla val = 1 key = :blubb val = 2.0 key = :lala val = 10/3 nil
05:22clgvoh sexpbot omits line-ends...
05:23bennylutclgv, its ok i get the picture :)
05:23clgvI thought so ;)
05:25clgvyo might consider using destructuring in the fn
05:25clgv&(dorun (map (fn [[k v]] (println (str "key = " k " val = " v))) {:bla 1 :blubb 2.0 :lala 10/3}))
05:25sexpbot⟹ key = :bla val = 1 key = :blubb val = 2.0 key = :lala val = 10/3 nil
05:29the-anomehi
05:33bennylutclgv, thank again :)
08:35TimMcThis is because C is a toy language originally intended for implementing an OS to so a guy could write a chess program.
08:35TimMcAck, sorry -- hadn't scrolled down.
08:37bawrThat reminds me - if I name some of my functions like X<-Y, taking Y and returning X, will people hate me? ;)
08:38bawrThis is probably due to some Hungarian Notation virus, really.
08:46ttmrichterTimMc: It wasn't a chess program. It was Space War, if memory serves.
08:47TimMcIt wasn't Ken what's-his-face at Bell Labs, wanting to write a chess AI opponent on spare hardware?
08:47TimMcThat's what one of my profs told me.
08:49ttmrichterNope. It was tragically far goofier than that.
08:49ttmrichterA chess AI would have a bit of cachet.
08:50ttmrichterUnix started life as a quick and dirty OS for a PDP-7 to run Space War.
08:50ttmrichterC started as a portable assembler to move Unix to a PDP-11.
08:51ttmrichter(I may have the name of the game wrong in retrospect -- it was Space something, but that something might be War or something else.)
08:57ttmrichterAh, here we are! Space Travel. http://people.fas.harvard.edu/~lib215/reference/history/spacetravel.html
09:01TimMchaha
09:19pyrTimMc: i got my pb right fixed it with a lazy-seq
10:27TimMcMakes sense.
10:48TimMcArgh, I just hit C-x C-s to save a doc in another program -- emacs is eating my brain!
10:49clgvlol. that isnt exclusive to emacs. I did strg+s when I had the impulse to temporary save a comment I was posting in a wiki ;)
10:50clgvit gets really stupid if paranoia kicks in and you'll end up pressing strg+s multiple times without a change ;)
10:52TimMcstrg?
10:52clgvoops. in english: ctrl ;)
10:52TimMcah
10:53clgvlol the left one already has no caption anymore
10:53TimMcWhen I do that, the browser prompts me for a filename to save the page to. >_<
10:53clgvyeah. thats the problem ;)
10:54TimMcWha makes it worse is that some pages (e.g. Google Docs) will capture and use the keystroke.
10:54clgvbut if they save the data it's probably ok ;)
10:54clgvdeleting it without backup would be a real killer feature ;)
10:57TimMcI've been thinking about making a website that violates as many user expectations as possible. I may use that idea. :-)
10:58clgvlol. send me the link on completion ;)
10:59TimMcIt's just an idea I'm kicking around.
11:11eckrothmacros that use macros are a bit challenging for me; specifically, if I have multiple namespaces that each have a unique macro, and each of these macros use some common macro, where do I put the common macro?
11:14clgvthe question remains the same if you replace macro by function ;)
11:14clgvdoes it sound easier now?
11:15clgvI would place it in a namespace for itself that communicates its "common" notion
11:16clgvperhaps you have other common definitions then you could put the together
11:16clgvs/the/them/
11:16sexpbot<clgv> perhaps you have othemr common definitions themn you could put them togethemr
11:16clgvoops
11:17eckrothI've had confusing experiences in which I felt that the common macro wasn't found, that it had to be local (duplicated for each use); I'll run a few tests right now
11:18clgvthat sounds strange.
11:24eckrothclgv: yeah, I can't reproduce the behavior on a simple test; I suppose you're right :)
11:24clgvI used macros across namespace boundaries ;)
11:29dfanWhat's the idiomatic way to construct a map with precomputed values? I did it 'by hand' with (apply hash-map (apply concat (for [n (range 0 100)] [n (f n)]))) but that seems suspiciously verbose
11:30clgvdfan: you could use map-cat instead
11:30eckroth(reduce (fn [m n] (assoc m n (f n))) {} (range 0 100)) ?
11:31DespiteItAllsounds like a job for map-indexed
11:31dfanclgv: mapcat, you mean? I don't see how that's relevant here
11:31clgvlike: (apply hash-map (mapcat (fn [n] [n (f n)]) (range 0 100))
11:31DespiteItAll(map-indexed f (range 0 100))
11:32DespiteItAllbut for the more general case, I use apply hash-map. I've had that catch mistakes that reduce/assoc wouldn't catch (duplicate keys)
11:33dfanAha, OK, you're using mapcat to combine my (concat (for))
11:33clgvyes
11:33DespiteItAlloh, duh, map-indexed doesn't return a map, so you'd still need apply hash-map
11:34clgvyeah. and he doesnt the index-property in this case at all ;)
11:34clgvthats only usefull when you iterate over other "objects"
11:35dfanOK, thanks, it sounds like there's nothing ridculously shorter
11:35clgvnot really, since you have to create that list
11:36DespiteItAllclgv: Yep, I smoke lots of crack.
11:36DespiteItAllAt best I was thinking of zipmap, but really I'm not making any sense
11:36clgvyou shouldn't - it effects health and sanity ;)
11:37DespiteItAll(zipmap (range 100) (map f (range 100)))
11:38DespiteItAllbut that's not really any clearer
11:38dfanYeah, although there I'm duplicating (range 100)
11:38dfanI can make a little helper function, I just thought that maybe said helper function already existed
11:39DespiteItAllThis seems like a common enough case that there should be.
11:41clgvyou think?
11:41clgvthe most general is the hash-map with the list of key-val pairs
11:42dfanand I like zipmap best as the way to write that helper function - I didn't like using it at the top level because it forced me to duplicate the domain, but it's fine inside the function
11:42clgv(defn create-hash-map [f coll] ...) ?
11:43dfanRight, I now have (defn make-hash-map [f vals] (zipmap vals (map f vals)))
11:43clgv&(doc zipmap)
11:43sexpbot⟹ "([keys vals]); Returns a map with the keys mapped to the corresponding vals."
11:44DespiteItAlldfan: I would put vals in a let, that way if it's a calculated list it won't be calculated twice
11:45dfanHow would vals get calculated twice?
11:45clgvDespiteItAll: like his defn above it's also calculated only ones ;)
11:45clgvs/ones/once/
11:45sexpbot<clgv> DespiteItAll: like his defn above it's also calculated only once ;)
11:45DespiteItAllyeah, ok
11:46dfanThanks all
11:50ApeShotSo I've been reading about how to implement lazy sequence functions and noticed here
11:50ApeShothttp://clojure.org/lazy
11:50ApeShotthat recursive calls in a lazy-seq block are always proper recursions rather than "recur" forms.
11:51ApeShotDoesn't this somewhat limit the usefulness of lots of functions, like map and filter, which now, though lazy, can also blow the stack?
11:51ApeShotOr does lazy-seq somehow trampoline them?
11:51stuartsierrait's similar to trampolining
11:52stuartsierraa lazy seq consists of lazy cons cells, ...
11:52stuartsierra… which are pairs sort of like <fn to return first>, <fn to return rest>
11:53ApeShotYes, as soon as a typed the question, I realized it was probably a de facto trampoline
11:53ApeShotGood to know, though
11:55TimMcApeShot: Look at the source for LazySeq. You can see the trampolining code, it's pretty cool.
11:56ApeShotrad
11:56ApeShotClojure is pretty slick
11:56ApeShotWill we get proper tail calls when the JVM supports them or are the contours of the language comfortable with explicit or trampolined self-recursion
11:56TimMcI believe this is it: https://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lang/LazySeq.java#L42
11:57clgvyes it is
11:59bawrI vaguely remember that explicit tail calls were meant to stay the way they are.
12:00ApeShotI like the idea of tail calls being made explicit, but not the idea of being limited to self-tail-calls
12:01ApeShotAlthough I can't say I've had too many experiences where I really wanted to tail call somewhere else
12:02ApeShotIt just seems like it would be nice to remove the limitation
12:03clgvI dont understand your case completely
12:03clgvis that other function calling the one with the tail call again?
12:04clgvfor mutual recursion you can use trmpoline afaik
12:04ApeShotSo recur simulates a tail call to the same call points as the context
12:04ApeShotself-recursion
12:04clgvself-recursion has to be the same function ;)
12:04ApeShotTrue tail calls clear the stack context before any tail call at all
12:04ApeShotin clojure, yes
12:04ApeShotyou can't "recur" to somewhere else
12:04ApeShotOnly to the current function
12:04ApeShotThis is less general than full tail call optimization
12:05clgvI would say the "self" in self-recursion defines that it is the same function
12:05ApeShotclgv: obviously
12:05clgvso you cant call another function in a self-recursion ;)
12:05ApeShotclgv: I am wondering if there are plans to provide explicit or implicit tail calls when the JVM is more modernized
12:07TimMcThe problem will be backwards compatibility of new programs.
12:08ApeShotI don't see how it would break backwards compat
12:09ApeShotIf tail calls become implicit, then nothing will change semantically in the language
12:09ApeShotif you add explicit tail calls
12:09TimMcWell, say you write a program for JVM 1.8 or whatever, relyn on implicit TCO.
12:09ApeShotsay with a (tail destination & args) form like "recur" then old programs should be fine
12:09ApeShotOh, sure
12:09ApeShotThat kind
12:09TimMcThen run it on 1.6.
12:09ApeShotNew programs won't run on the old version
12:09DespiteItAllI think it should always be explicit
12:10TimMcDespiteItAll: +1 to that.
12:10ApeShotDespiteItAll: I sort of agree witht his
12:10ApeShotAt least the compiler can bark at you if you accidentally don't call in a tail position
12:10ApeShotAnd I suppose it allows more optimization, probably
12:11TimMcI believe the discussion for *Java* 1.7 included a "become" alternative for "return".
12:12TimMcTHat would match up to a JVM TCO feature and allow compile-time checking.
12:12DespiteItAllinteresting
12:12pdclj-http returns response headers as a map, but it seems that is inherently broken for responses that set multiple cookies, since you have 2+ "Set-Cookie" headers in the response
12:12pdyou can only ever get access to the last one
12:12pdanyone know how ring deals with this?
12:13TimMcDespiteItAll: Or maybe, since become is not a reserved keyword yet, they could repurpose goto. :-P
12:13TimMcpd: Ooof, that's irritating.
12:13DespiteItAllI would love to see a GOTO comeback
12:13DespiteItAllI want to see a bunch of OOPers using GOTO
12:14clgvdoesnt like the semantic behind goto
12:15TimMcHmm, I guess they do sometimes add keywords.
12:15TimMchttp://download.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html
12:16TimMcThey added enum in v1.5 and assert in v1.4.
12:18clgvuh. whats strictfp?
12:19TimMcStrict floating point.
12:19TimMcNever used it myself.
12:20TimMcIt's for portability, apparently.
12:20TimMchttps://secure.wikimedia.org/wikipedia/en/wiki/Strictfp
12:22clgvah ok. never heard of it before ;)
12:22TimMcI didn't know what it was *for* until I looked it up just now, even though I've known of the keyword for... about a decade. :-P
12:26TimMcOK, some web pages are alleging that TCO is being worked on but isn't likely to land in v1.7, but has a good chance at v1.8.
12:30pdnow i need to work with a modified clj-http, what's the most reasonable way to go about doing that when my project uses lein?
12:31TimMcpd: Is it a local modification, or did you find a public fork?
12:31pdlocal, i just cloned the repo and added in some cookie handling code.
12:35TimMcI think there's a way you can install a local project using lein.
12:36TimMcSee if "lein install" is what you want.
12:40pdTimMc: yeah that will work, ty
12:41pdtho it feels like it's going to be tedious to edit, lein install clj-http, then update deps in my project, then hit the repl to see if it's working out, ... =)
12:42TimMcpd: Try writing some tests in your clj-http fork
12:42pdi have
12:45TimMcMaybe there's a way of asking for local deps.
12:45TimMcYou'll still have to lein clean && lein deps && lein test
14:13pyrhi
14:13pyrwhile sending a blocking function to an agent
14:13pyr(this specific function constructs a seq with lazy-seq)
14:14pyrawait-for doesn't exhibit the correct behavior
14:14pyrin that it never returns
14:14pyrsend and send-off to the agent makes no difference
14:15pyrdo i have to agentify each call in the function being sent ?
14:16bennyluthi all, i want to define a new exception from within clojure using deftype - i want to be able to supply message to the this exception using the extended exception constractor - can it be done?
14:27bennyluthi all, i want to define a new exception from within clojure using deftype - i want to be able to supply message to the this exception using the extended exception constractor - can it be done?
14:29tomojException is a class, deftype implements interfaces/protocols
14:29TimMcbennylut: Clojure frowns on extending concrete classes, by the way.
14:31tomojI think there are only two options if you insist: gen-class and proxy
14:31TimMcYou can alway extend it in Java and use it in Clojure.
14:37TimMcbennylut: More importantly, perhaps... why do you need another exception type?
15:07khaliGis filter a good way to search a vector?
15:08parasebakhaliG: not very good, since it returns another seq. filter is good to, well, filter the vector
15:08parasebakhaliG: you may want to use some
15:08paraseba(some #(= :yes %) [:no :yes :maybe])
15:09khaliGparaseba, ah good point, i glanced past that before but didn't realise it wasn't just a predicate like its company
15:11parasebakhaliG: a common idiom is to use sets as predicates with some, since sets are function of their values
15:11paraseba(some #{1 2 3} some-seq)
15:12khaliGparaseba, understood
15:21khaliGis .equals the right way to compare strings?
15:25mduerksenno, = is
15:25parasebakhaliG: you can use .equals, but its easier to use =
15:26khaliGthat's nice and consistent
15:27mduerksenyes, i love that about clojure. comparison is generally very simple here, no need to worry about pointer-equivalence like in java and the like
15:28parasebayes, comparison turns out very easy for clojure types, since everything is immutable
15:28khaliGbut strings are immutable in java too
15:29parasebathey are java strings
15:30khaliGis this illegal ... (fn [{_ name __ value}] ...)
15:31amalloykhaliG: it's legal, but probably not what you meant
15:31khaliG"Unable to resolve symbol: value in this context"
15:31khaliGhm lets see
15:32khaliGthe dashes are keywords which i dont care about -- and the other two are values which i do
15:32khaliGeg, {:name "Bodyweight", :value "197"}
15:33parasebakhaliG: try {_ :name _ :value}
15:33amalloy&((fn [{:keys [name value]}] (str name " " value)) {:name "Bodyweight", :value "197"})
15:33sexpbot⟹ "Bodyweight 197"
15:34parasebakhaliG: { name1 key1 name2 key2}
15:35Chousukeor use the :keys shortcut like amalloy did
15:35Chousukeif there are keys you don't care about, those don't matter anyway
15:35amalloyright, the above is shorthand for ##((fn [{name :name value :value}] (str name " " value)) {:name "Bodyweight", :value "197"})
15:35sexpbot⟹ "Bodyweight 197"
15:40amalloykhaliG: satisfactory?
15:40khaliGyes, i just finished testing the defn and it works beautifully
15:40khaliGmany thanks
15:41khaliGjust one last question -- "12" to a number, should i use read-string, or (. Integer parseInt "12") like in Java
15:42khaliGi'm thinking read-string is more robust since it doesn't care about the size of the number
15:42khaliGbut if efficient?
15:43Chousukeit uses the java parsers
15:49TimMc,(read-string "१२३")
15:49clojurebotjava.lang.RuntimeException: java.lang.NumberFormatException: Invalid number: १२३
15:50TimMcFascinating. It knew the characters were numerals, but couldn't use them.
15:51amalloyTimMc: i get that a lot when people read my handwriting
15:59khaliGhm i could swear i saw a zip/unzip function somewhere.. :/
16:00brehautkhaliG: zipping lists?
16:00brehautif so, map and apply map is your friend
16:01khaliGbrehaut, i want to go from [[x1 y1] [x2 y2]...] to [x1 x2 ..] and [y1 y2 ..]
16:01TimMcmap vector
16:02brehaut,(map vector [[:x1 :y2] [:y1 :y2]])
16:02clojurebot([[:x1 :y2]] [[:y1 :y2]])
16:02tomojneed to apply it
16:02brehautah yeah
16:02brehaut,(apply map vector [[:x1 :y2] [:y1 :y2]])
16:02clojurebot([:x1 :y1] [:y2 :y2])
16:03brehaut,(apply map vector (apply map vector [[:x1 :y2] [:y1 :y2]]))
16:03clojurebot([:x1 :y2] [:y1 :y2])
16:03brehautthings that are their own duals are cool
16:04tomojis that just transpose?
16:04brehauttomoj: yes
16:05amac,(interleave [:x1 :y1] [:x2 :y2])
16:05clojurebot(:x1 :x2 :y1 :y2)
16:08khaliGapply map vector works, not to understand why?!
16:08khaliGhm i think i get it, that's very cool
16:08brehautkhaliG: its pretty simple if you take the time
16:09amacyou're mapping the first items in each input vec into an output vector, then the second...
16:09brehautkhaliG: you dont need specific zip and unzip functions in a language with varargs and apply semantics
16:10TimMcbrehaut: But if you *do* have zip, you don't have to remember what "map vector" implies each time you read it.
16:10amac,(map vector [1 2] [3 4])
16:10clojurebot([1 3] [2 4])
16:10amacis the same as:
16:10brehautTimMc: sure but id rather it was called transpose
16:10amac,(vector [1] [3])
16:10clojurebot[[1] [3]]
16:10TimMcbrehaut: Yeah, that is a better name.
16:10amac,(vector 2 4)
16:10clojurebot[2 4]
16:11amacuhh, first one is wrong sry
16:11tomojmap is just zipWith with arbitrary arity?
16:13khaliGbut yes it would look clearer with an explicit function
16:13khaliGi'm sure incanter has one, which is probably where i saw it, now that i think about it
16:14TimMcThere is such a profusion of programming languages right now. Has this always been the case, and most languages just get forgotton?
16:15TimMc(forgotten, even)
16:15khaliGnope i'm mistaken, it's not in incanter either
16:15tomojI think naturally with absolutely more programmers there will be absolutely more languages
16:15TimMcheh
16:15tomojthe history of the distribution of survival time would be interesting though
16:15TimMcI was thinking of the availability of tools, but you raise an excellent point.
16:16khaliGi'm not even trying to write clojure concisely it's just coming out that way
16:17brehautthere are more runtime platforms to build languages on now too, and you can get away with a slow homebrew runtime for many tasks
16:22tsdhI want to write a function that either gets a Vertex (some Java object) + some other args, or a seq of Vertex + some other args. How can I dispatch between the two?
16:22clojurebothttp://www.math.chalmers.se/~rjmh/Papers/whyfp.pdf
16:23amalloytsdh: your specification is unclear. by the second case do you mean [v other other], or [v1 v2 v2] other other?
16:24TimMctsdh: multimethod dispatching on first of args?
16:25tsdhamalloy: One would be (--> v1 :type 'foo) and the other (--> [v1 v2 v3] :type 'foo)
16:26tsdhTimMc: You mean (fn [c & _] (class c))? But what's the class of a seq?
16:26TimMc:default :-P
16:26TimMc,(class (seq [1 2 3]))
16:26clojurebotclojure.lang.PersistentVector$ChunkedSeq
16:26TimMcWell, ISeq or something
16:26Chousukedon't rely on the classes
16:27amacseq is an interface
16:27Chousukeright. though you can call seq on more than just ISeqs
16:27TimMchrm
16:27ChousukeI'd just check if the thing is a vertex and treat it as a seqable thing if it isn't.
16:27TimMc,(doc parents)
16:27clojurebot"([tag] [h tag]); Returns the immediate parents of tag, either via a Java type inheritance relationship or a relationship established via derive. h must be a hierarchy obtained from make-hierarchy, i...
16:27Chousukewith an if
16:27amaccollections have functions that coerce them into seqs, but their class remains the collection type
16:28amac(type (seq "aoeu"))
16:28amac,(type (seq "aoeu"))
16:28clojurebotclojure.lang.StringSeq
16:28amac,(type (seq [1 2 3]))
16:28clojurebotclojure.lang.PersistentVector$ChunkedSeq
16:28TimMc,(parents (class (seq "a")))
16:28clojurebot#{clojure.lang.ASeq clojure.lang.IndexedSeq}
16:28tsdhChousuke: Hm, well, yes. I think that's the simplest solution. :-)
16:30amalloyTimMc: parents is not what you want: ##(supers (class (seq "a")))
16:30sexpbot⟹ #{clojure.lang.Sequential clojure.lang.IPersistentCollection java.lang.Object clojure.lang.Obj java.io.Serializable clojure.lang.IMeta clojure.lang.Counted java.lang.Iterable clojure.lang.IndexedSeq java.util.List clojure.lang.ASeq clojure.lang.IObj java.util.Collect... http://gist.github.com/857695
16:31TimMc,(doc supers)
16:31clojurebot"([class]); Returns the immediate and indirect superclasses and interfaces of c, if any"
16:31tsdhWhy do vectors not implement ISeq?
16:31amacthey do
16:31tsdh,(seq? [1 2 3])
16:31clojurebotfalse
16:31amac,(seq? (seq [1 2 3]))
16:31clojurebottrue
16:31TimMctsdh: They aren't seqs, they're collections.
16:31amacthey need to be coerced, but it happens automatically for seq functions
16:32pyrso there are still ways to make agents block even with await-for and send-off, right ?
16:32lpetitHello guys. Something totally off topic: for counterclockwise, I'd like to host the eclipse update site (it's really just a bunch of files hosted on an http server) myself, so that I can get by some way the number of downloads, for each version, per day/month, etc.
16:32lpetitAnd now the question : what to use ? awstats ? webalizer ? analog ? I will not do intensive usage, I do not want to specialize on log statistics. If you know the best fit for my usecase, thanks in advance for sharing your thoughts.
16:33amacmost webservers record access logs, just parse the logs to get the activity.
16:34amac...not entirely sure I understand the problem scope though
16:35lpetitamac: yes I understand that. The problem scope is: I publish a new version of counterclockwise, say 0.2.0. It's a bunch of files, one of whose I can count downloads on to know how many installations of the plugin have been made.
16:36technomancylpetit: I host downloads on github, and I can see it broken down by version, but not by time.
16:37technomancynot too flexible, but definitely easy: https://github.com/technomancy/leiningen/downloads
16:38amacsend github a patch to pull analytics by date, solve the problem for everybody :)
16:38lpetittechnomancy: an Eclipse update site is a set of related files, one located in say /updatesite/site.xml, and the others in say /updatesite/plugins/ccw.jar , /updatesite/features/ccw_feature.jar . So there is an organization of files from /updatesite/ URI which is somehow expected by the Eclipse client
16:38technomancyah, gotcha
16:39lpetittechnomancy: yeah :-(. So I really need some kind of ftp-like http exposure
16:41lpetitI hoped I would not have to dig into apache configuration files again, seems like I was wrong :-(
16:41amaclast year I started using lighttpd instead of apache, my life is now better
16:41amacseriously, break up with apache and never look back
16:41lpetitUnless I find some java webapp which would do this at the application level (serve as a proxy for the filesystem, and register logs for me). I think I can suffer the performance penalty.
16:42brehautlpetit: that should be fairly straight forward to cook up with ring
16:42amacactually yeah
16:42amalloygood point
16:42brehautlpetit: there is static serving middleware, and it would be trivial to wrap that in another middleware to do the counting
16:42lpetitbrehaut: sure, it's just that I want to stay focused on my need.
16:42amacserve the files through the file middleware, and wrap it with a counter
16:43RaynesI never got a chance to breakup with apache. My first webserver was nginx.
16:43lpetitNow, if "all in all" it would cost me less time to play with ring, then yeah, that might be fun
16:43amacRaynes: I wouldn't wish an apache configuration on my worst enemy
16:43lpetitthat's tempting, indeed :)
16:44brehautlpetit: the ring end is the easy part, i think you'd probably spend more time faffing about getting it running on your server with apache and what not than actually developing it
16:44lpetitApache configuration is like monkey patching, ask google, copy & adapt :-(
16:44Raynesamac: I wouldn't wish nginx documentation on the cleverest webserver newbie.
16:44amachahaha
16:45RaynesThere isn't much in the way of "what is a webserver and how do I make it serve web?" documentation on nginx that I could find.
16:46amacthere isn't a massive amount of docs out there for lighttpd, but its an incredibly simple setup
16:46brehautRaynes: a web server is an amorphous blob that consumes http requests, and does something undefined to produce a new http response.
16:46lpetitbrehaut: it always seems easy when we're sufficiently far from the detail. But I'm pretty sure that if I'm going this road, sooner or later I'd want some stats based on day, then on geography, and sooner or later I'll wake up having reinventing half webalizer features, albeit with my proprietary log file format :-(
16:53amalloypyr: seems so, yeah
16:54pyramalloy: well then i don't get why this blocks forever for me
16:55amalloy&(let [a (agent 0)] (send-off a #(do (Thread/sleep 4000) (inc %))) (await-for 2000 a))
16:55sexpbot⟹ false
16:55pyryep
16:55amalloy&(time (let [a (agent 0)] (send-off a #(do (Thread/sleep 4000) (inc %))) (await-for 2000 a) @a))
16:55sexpbot⟹ "Elapsed time: 2001.618224 msecs" 0
16:56pyrmy func calls lazy-seq on itself
16:56pyri wonder if that's the case
16:57amalloypyr: then your agent is returning a lazy seq instantaneously and you're wasting a bunch of time derefing, probably
16:57amalloytry wrapping the await and the deref with (time)
16:58pyrtime ?
16:58amalloywell, the deref will always be instantaneous. so maybe (time (doall @a))
16:58pyroh
16:58pyrtrue
16:59lpetittechnomancy: you gave me an idea !
16:59lpetittechnomancy: from the docs of artifacts.xml in the eclipse.org website: "It is possible to change those rules to have a filter matching for a particular artifact and change the output to point to a specific location."
17:00lpetittechnomancy: so I can change the default filter rule, and have all my plugins and features locations resolve to https://github.com/downloads/laurentpetit/ccw/*.jar
17:00lpetityay !
17:02lpetitI need to find a way to automate this so that I don't have to change the file by hand for each delivery
17:04lpetitHmm
17:14pyrgaah
17:14amachas anyone ever tried to send bulkmail through a gmail account? will them deliver them? (about 300 messages)
17:14pyrit blocks with loop / recur too
17:14amacusing a lib like this one: http://blog.8thlight.com/articles/2010/4/21/mmemail-my-first-clojure-open-source-contribution
17:15pyrso it seems that if you poll the network await gets tricked
17:18amalloypyr: i am dubious. maybe if you gisted some actual code...
17:18pyrwill do
17:22pyrhttp://pastie.org/1640882
17:23pyrthere's two versions that return a message list
17:23pyramqp-topic is a lazy-seq, amqp-topic2 a loop/recur, both block even when inside an agent
17:28amalloyhm. seems like it ought to work, because mq is accepting InterruptedException
17:30amalloyas a side note though you're abusing agents here if you don't care about their value. just use future, future-done?, and future-cancel
17:31TimMcI believe ants.clj abuses agents the same way.
17:31TimMcWere futures not available yet?
17:32TimMc(I think it is a Clojure 1.1 vintage.)
17:32pyrah, great
17:32brehautTimMc: ants is pre 1.0
17:32TimMcbrehaut: yikes!
17:32pyrwhen did future get in clojure ?
17:33amalloy&(-> future var meta :since)
17:33sexpbot⟹ nil
17:33amalloyhm
17:33amalloy&(meta #'future)
17:33sexpbot⟹ {:macro true, :ns #<Namespace clojure.core>, :name future, :file "clojure/core.clj", :line 5407, :arglists ([& body]), :added "1.1", :doc "Takes a body of expressions and yields a future object that will\n invoke the body in another thread, and will cache the result... http://gist.github.com/857799
17:33brehaut&(-> future var meta :added
17:33sexpbotjava.lang.Exception: EOF while reading
17:33amac&(source future)
17:33sexpbotjava.lang.Exception: Unable to resolve symbol: source in this context
17:33brehaut&(-> future var meta :added)
17:33sexpbot⟹ "1.1"
17:34pyrok seems good
17:34pyrthere's no reason why my stuff will work with futures but using the right constructs is good
17:34TimMcOh hey, that uses java.util.concurrent.Future
17:34raekthe executors framework of java has been available for clojure users all the time, though...
17:35pyranything like awai-for for futures ?
17:35raekpyr: (.get ftr TimeUnit/SECONDS 10)
17:36pyr'k makes sense
17:36raekpyr: I wrote a ppost about this: http://blog.raek.se/2011/01/24/executors-in-clojure/
17:36pyrmuch more sense than what i did
17:38raekagents is a reference primitive built on top of executors and does not replace executors
17:39pyrthanks a lot, your blog post is really thorough
17:39pyrand will be of great help
17:39raekit would be nice if there was some documentation for certain java classes from a clojure perspective
17:39TimMcI need to learn about Executors. I don't think it existed the last time I used Java threads.
17:40amalloyTimMc: 1.5, right?
17:44TimMcMost likely v1.4.
17:44TimMcOr even v1.2.
17:45amalloyi meant that's when executors appeared
17:45TimMcAh, OK. I have no idea.
17:45TimMcI just learned it existed this week,
17:45TimMc.
17:52tomojpyr: I wonder if lamina may be relevant to your interests
17:59amalloyraek: looking at your bloggy thing now. "a units of work" is an arity mismatch
18:07pyrtomoj: i'll look it up
18:07pyrwell future don't get me a free pass either :(
18:09raekamalloy: thanks for spotting that!
18:15tomojpyr: e.g. in master (wait-for-result (task (Thread/sleep 1000) "foo") 900) throws a TimeoutException while (wait-for-result (task (Thread/sleep 1000) "foo") 1100) returns "foo"
18:16tomojtask being a macro similar to future except that it returns a result channel
18:17tomojbut lots of related stuff is brand new and unstable
18:17tomoj:(
18:19pyrtomoj: if the underlying mechanism is the same than for agents and futures it might not work either
18:20pyr\o/
18:20tomojthe underlying mechanism is quite different, if I understand what you mean
18:21pyrok, with futures and the lazy-seq version it would fail but with the loop/recur one i get a result
18:21tomojtask does use an executor, and by default (I think) the soloExecutor agents use for send-off (right?). but otherwise, totally different
18:22pyrtomoj: ok
18:23tomojusing lamina just for that timeout thing in particular, of course, would be silly
18:25pyryeah the idea of it is really interesting
18:25amalloytomoj: less silly than using incanter to get an (average) function, at least
18:28pyrtomoj: the siphon approach is really interesting yes
18:28pyri'll look into it seriously
18:28clojurebotI don't understand.
18:29pyrwell guys thanks for your help, time to catch some sleep
18:47Nanakhieltomoj, my old friend
18:47NanakhielI love what you've done with your beard.
18:47tomojyou call this a beard?
18:48Nanakhieltomoj, no idea, I'm just quoting this comedy group.
18:49Nanakhieltomoj, how much beard do you have?
18:54tomojnot enough to call it that
20:05preyaloneClojure can't find my *.clj files to compile them unless I type (set! *compile-path* (str *compile-path* ":.")). Which config file could I put this in?
20:06TimMcpreyalone: What are you using to compile?
20:06amacpreyalone: do you use leiningen?
20:06amalloypreyalone: use a build tool like cake or leiningen instead of doing it by hand
20:06preyaloneI just want to compile hello.clj. I'll use Leiningen for anything more complicated.
20:06preyaloneTimMc: (compile 'hello)
20:07amacleiningen isn't as painful as you think
20:07amalloypreyalone: i literally have no idea how to compile things without a build tool. it's easier to use one than not to
20:07preyaloneOMG
20:07amactype 'lein new projectname' and it'll populate everything you need
20:08preyaloneI don't want any more files or directories than hello.clj.
20:08TimMcpreyalone: You know you don't have to compile Ahead-Of-Time to run Clojure code?
20:08amacmodify you src/project/core.clj file to (println "hello world")
20:08amacthen lein run
20:08preyaloneTimMC: I do to test how various command line arguments will be evaluated by interpreted vs compiled code.
20:08preyaloneIs there ~/.cljrc or something similar?
20:10TimMcpreyalone: Leiningen is super-easy to install (local, only takes a minute, uses ~/.lein for caching). It's dead easy to use, and pretty standard. (Cake is similar from a basic usage perspective.)
20:10amacI think you need to add :gen-class to your ns, then run javac -cp clojure.jar hello.clj
20:10amac...never actually done it manually
20:10preyaloneamac: What does :gen-class do?
20:11TimMcI did it manually maybe once so that I knew how, and then started using a build tool and never looked back.
20:11amachttp://clojure.org/compilation
20:11amacthat should have some more details :)
20:11preyaloneamac: Thanks man
20:12amac&(doc gen-class)
20:12sexpbot⟹ "Macro ([& options]); When compiling, generates compiled bytecode for a class with the given package-qualified :name (which, as all names in these parameters, can be a string or symbol), and writes the .class file to the *compile-path* directory. When not compiling, ... http://gist.github.com/857934
20:15preyaloneSide note: When is -main run?
20:15preyaloneCause clj hello.clj doesn't run it.
20:16amacI know there's a resource in jars that specifies the name, I only know how to config it with leiningen but it can be specified manually
20:16amacs/name/main
20:16sexpbot<amac> I know there's a resource in jars that specifies the main, I only know how to config it with leiningen but it can be specified manually
20:16preyaloneamac: Adding :gen-class doesn't appear to do anything.
20:17amalloyamac: META-INF/MANIFEST.MF has a Main-Class key iirc
20:17amacamalloy: that sounds familiar
20:17preyalone-main is only run when the script is compiled ???
20:18amalloypreyalone: or when you call (-main) yourself. it's not that hard
20:19preyaloneamalloy: Surprises like that slow me down.
20:19preyaloneamalloy: My goal is to get a behavior like Ruby's if __FILE__ == $0 main end
20:19amalloypreyalone: then take the advice of everyone in this channel and start using tools that hide those surprises from you
20:19preyaloneamalloy: Those tools don't hide the main/-main surprise.
20:20TimMcpreyalone: Yes they do!
20:20TimMcYou add :main to your project.clj and DONE.
20:20preyaloneThose tools will not make my script run (main) when it's interpreted.
20:20amaccave to the peer pressure.
20:20TimMcpreyalone: Load-file it in a REPL and call (-main)
20:20amacall the cool kids use leiningen.
20:20preyaloneTimMC: You mean add :main to the namespace?
20:20TimMcNo, to the Leiningen or Cake project.clj file.
20:21TimMcAnyway, the distinction you want is compiled on the fly vs. AOT.
20:21TimMcClojure is never interpreted.
20:21TimMcBuild tools give you both.
20:22preyaloneTimMc. Clojure interprets user commands. The fact that behind the scenes they are compiled to byte code is an arbitrary qualification.
20:22TimMcSure, have it your way.
20:22brehautTimMc: marginally correct ;) any JVM bytecodes may be interpreted during their lifetime but that is irrespective of JIT or AOT for the clojure compiler
20:23amacjit compiling still blows my mind
20:23amacthat is straight up magic
20:23preyaloneWhat's that about adding :main to my file? I have a main function specified. Should I add something to my namespace declaration?
20:24TimMcpreyalone: :main is not added to your program.
20:27brehautpreyalone: have you read and digested all of http://clojure.org/compilation ?
20:27preyalonebrehaut: I'm reading it right now.
20:28preyalonebrehaut: The problem is *compile-path* does not have "." by default. When I add that, hello.clj compiles just fine.
20:29brehautthen do that?
20:29preyalonebrehaut: Clojure has no trouble running hello.clj, it just can't find it when I (compile 'hello).
20:29TimMcThere is no reason for *compile-path* to have "." in it by default.
20:30brehautpreyalone: personally i think doing it by hand is madness
20:31amac,*compile-path*
20:31clojurebotnil
20:31preyalonebrehaut: On the other hand, needing tools just to compile Hello World is madness.
20:31preyaloneamac: "classes"
20:31brehautcompiling hello world is madness
20:31amacthere are step by step instructions for building hello world in that page I sent you
20:31amacsans tools
20:32brehautAOT Compiling that is
20:33amacalso, "hello world" is what clojurebot was born for :)
20:33dfan`Embarrassing question: How do I convert a sequence of chars to a string?
20:33preyaloneamac: Those instructions only work for the example Hello World that comes with Clojure, not the same file located on my Desktop.
20:34amalloydfan`: ##(apply str [\a \b \c])
20:34sexpbot⟹ "abc"
20:34TimMc,(str (seq "foo"))
20:34clojurebot"(\\f \\o \\o)"
20:34amac(reduce str [\a \b \r])
20:34TimMcworth a try
20:34preyaloneThis is rich: (compile 'clojure.examples.hello) java.io.FileNotFoundException: Could not locate clojure/examples/hello__init.class or clojure/examples/hello.clj on classpath: (NO_SOURCE_FILE:0)
20:34amalloyor clojure.string/join, if you want anything fancier than plain concatenation
20:34TimMcNo wait, it wasn't.
20:34amac,(reduce str [\a \o \e \u])
20:34clojurebot"aoeu"
20:34dfan`What clojurebot said :)
20:34brehautpreyalone: is your file in the correct directory structure?
20:35dfan`amalloy: Thanks, perfect
20:35preyalonebrehaut: hello.clj is in /Users/andrew/Desktop.
20:35brehautpreyalone: then no, its not. put it in clojure/examples/
20:36preyalonebrehaut: That won't help. Did you see the above excerpt? My Clojure can't even compile the example scripts.
20:36preyaloneCould not locate clojure/examples/hello__init.class or clojure/examples/hello.clj on classpath: (NO_SOURCE_FILE:0)
20:36amalloypreyalone: good idae. ask for help, then reject it instead of trying it
20:36brehautpreyalone: to quote the error you are vomiting at me "clojure/examples/hello.clj on classpath: "
20:37brehautif you dont put your file where its _explicitly tell you it should be_ it wont work
20:37preyaloneall: MacPorts Clojure is having trouble finding ANYTHING, including the example scripts. Inserting my code there will not help me.
20:37TimMcpreyalone: Why don't you try it, hm?
20:38preyaloneTHIS: (compile 'clojure.examples.hello) FAILS on my system.
20:38brehauti let lein manage my project dependancies such as clojure, rather than some random package manager
20:38amac,(time (apply str [\a\o\e\u]))
20:38clojurebot"Elapsed time: 0.128 msecs"
20:38clojurebot"aoeu"
20:38preyaloneStraight from the Clojure - compilation tutorial: http://pastebin.com/raw.php?i=7StS2qvW
20:38amac,(time (reduce str [\a\o\e\u]))
20:38clojurebot"Elapsed time: 0.15 msecs"
20:38clojurebot"aoeu"
20:39amacamalloy: damn, you win.
20:39preyalonebrehaut: That might help.
20:39amalloyamac: it's because str uses a StringBuilder internally
20:39TimMcGood to know.
20:39amalloyif it has to return a real String after every concatenation it can't do that optimization
20:39clojurebotIt's greek to me.
20:39preyaloneAnother problem is that Homebrew Chicken Scheme fails, MacPorts CLISP fails, and Fink SBCL fails. I need several package managers.
20:40amacthat is handy information
20:40brehautpreyalone: i cant give you any more suggestions. clojure namespaces must be in the matching directory structure. if you refuse to acknowledge that, you will never solve this
20:40amalloy$source str
20:40sexpbotstr is http://is.gd/ovOFFx
20:41preyalonebrehaut: Open my pastebin. http://pastebin.com/raw.php?i=7StS2qvW THE TUTORIAL DOESN'T WORK ON MY SYSTEM.
20:41brehautpreyalone: you have spent your last credit of good will.
20:41TimMcI'm already /ignore ing him.
20:41TimMcForgot to add -replies.
20:42amalloyi wonder why str uses an anonymous function instead of a loop
20:43amaccan loops be lazy?
20:43amalloyno, but neither is str
20:43amacit looks like it can be
20:44amalloyit can't
20:44amalloybecause a string is a single atomic object
20:44amalloyyou can't return part of a string and give out the rest later
20:46TimMcI see this (.x (toString)) syntax all over c.core -- is there a particular reason it isn't written (.toString x) ?
20:46amacyou can if the str is coerced into a seq
20:46amac(type (seq "aoeu"))
20:46amac,(type (seq "aoeu"))
20:46clojurebotclojure.lang.StringSeq
20:46TimMcamac: The wrapper is a seq, sure.
20:47amacyeah, I guess it still needs to have the underlying string before it can be coerced
20:47amacbut that's the only use case I can think of for lazy strings
20:47johnmn3any clojars.org admins in the house?
20:48TimMcNow, you can certainly make a lazy seq of characters, and the fn could take the same args as str.
20:48amalloyTimMc: i think the version in c.core is (a) faster to compile, and (b) possibly more correct if there happens to be an object so dumb as to have a field named toString
20:48amacbut when you create a str it would pull the entire lazy seq of chars
20:49TimMcamalloy: Ouch, I forgot about that.
20:49TimMcI had been wondering about how to deal with the rare case of identical field and method names, and now I know. :-)
20:51amac.(str \a \o (delay \e))
20:51amac,(str \a \o (delay \e))
20:51clojurebot"aoclojure.lang.Delay@2c5810"
20:51amaceww
20:51TimMcheh
20:58amalloyjohnmn3: i dropped an email to contact@clojars a week or so ago and haven't heard back. ping me if you get a hold of anyone
20:59johnmn3amalloy: yea, I forgot my password on there and sent in an email too.
20:59TimMcHas stuff on clojars been vetted in any fashion, or is it just a free-for-all registry of code repos?
20:59johnmn3pretty sure it's free-for-all
20:59amalloyTimMc: push anything you want
21:00johnmn3you register an ssh key though.. it's not like people can step on each other
21:00amalloy(shameless-plug http://hubpages.com/hub/Build-your-own-Clojure-toolkit mentions how easy it is to use clojars)
21:01brehautamalloy: haha i was just reading that
21:02amalloybrehaut: after i wrote a couple articles i started getting automatic plugs from planet clojure. it was pretty neat to see that they've used yahoo pipes to automatically incorporate my clojure articles into their feed
21:03brehautamalloy: yeah i noticed they did that with my site too
21:03brehautim tempted to make a special feed for them so its a bit more targetted
21:03amalloybrehaut: have you looked at the source of the pipe?
21:03amalloyit's probably targeted enough
21:03brehautamalloy: i dont have a yahoo account so i cant
21:04brehautamalloy: i think it looks for the word clojure in the body?
21:04brehauti know its not everything
21:04amalloymine is like "articles by amalloy with Clojure in the title or description"
21:04brehautbut its picking up my short links if they match
21:04amalloyah
21:04brehautand that often repeats things that are in the pipe already
21:04brehautwhich (IMO) is a bit lame
21:04amalloyyeah i see what you mean
21:05amalloyi only publish full-length articles so didn't consider that issue
21:05brehautyeah i think its fine for most people
21:05brehautwho have real content rather than links to other peoples content
21:18amalloyanyone have a link on getting started with Ring?
21:19amacamalloy: I've been figuring it out with the source examples, the tutorial space is light for clojure networking
21:20brehautamalloy, amac: http://mmcgrana.github.com/
21:20brehautLau has a couple of worked examples on his github too
21:21brehautalso wow, lein 1.1 thats an old tutorial
21:22amacalso, I'm using aleph which is even lighter on docs
21:22amacbut based on ring, so figuring ring out gets me 80% of the way there
21:23brehautaleph is a bunch more (for a lack of better word) experimental
21:24amacyeah, I've been trying to fix a bug all week parsing form post data, can't figure out if its a problem with my code (probably), aleph (also pretty likely), or ring (doubtful)
21:25amacbrehaut: have you played with aleph?
21:25brehautamac: its on my list but not yet
21:26amacbummer, I haven't run into anybody who's used it
21:26amacit actually seems pretty slick, if I can get it all working
21:27brehautit seems very slick yeah
21:27amalloyomg my computer says Hello world from Ring! this is exciting stuff
21:28brehautztellman's been putting a lot of thought into it and the channel's stuff in general. a lot of promise there in general
21:29amacamalloy: you're one step ahead of preyalone ;)
21:29amalloyhahahaha
21:29brehautbaha
21:29TimMc>_<
21:29brehautamalloy: have you got it saying hello world only once?
21:29amalloyeh?
21:30brehautmake your handler approximatly (fn [req] (prn "hello") {:body "Hello, world" :status 200})
21:30amalloywhat. noooo, side effects are evil, why would i prn
21:31brehautamalloy: so that you can see it handling each request in the console
21:31brehautrather than just what you see from the browser
21:31amalloypsh
21:32brehautalternative use a proxy tool i guess :)
21:32TimMcamalloy: At least it's not a JOptionPane
21:33amalloywhile i'm on the topic of learning new things, someone teach me how to manage multiple swank servers/repls from emacs
21:34joshuacamalloy, what I do is start the swank server on a different port and connect to it with another instance of emacs
21:34amaclein swank takes a port arg (defaults to 4005)
21:34amalloyamac: sure, i can start lots of servers
21:35amalloymanaging to use them sensibly is trickier
21:35amacthen M-x slime-connect in emacs to whichever running server you want
21:35amalloyand this...what, gives me multiple slime-repl buffers, each connected to a different server?
21:35amacerr, I guess you can only have one slime connection per instance of emacs
21:36amacfire up screen and start multiple emacses
21:36amacemacsen?
21:36amalloybarff
21:36amalloyemacsen, i believe
21:36amacI've never actually had a use for that word
21:36amalloyhah
21:41phenom_what's the call to convert a keyword to a string?
21:42amalloyname
21:42brehaut,(name :keyword)
21:42clojurebot"keyword"
21:42TimMc$findfn :phenom_ "phenom_"
21:42sexpbot[clojure.core/name clojure.contrib.string/as-str]
21:42phenom_amalloy: beautiful! thnx
21:43amacand oppositely, ##(keyword "aoeu")
21:43sexpbot⟹ :aoeu
21:43amalloyamalloy for speed, brehaut for clarity, and TimMc for teaching you to go fishing your own damn self :)
21:43amalloy$botsnack
21:43sexpbotamalloy: Thanks! Om nom nom!!
21:43amalloyTimMc: ^
21:43TimMcWe're all winnnars!
21:43brehauthaha :)
21:44brehautphenom_: name works on any clojure.lang.Named implementation (which i believe is just keyword and symbol at present)
21:44amacand my advice is to solve a different problem than the one you asked.
21:44TimMchaha, nice
21:44amalloy*chuckle*
21:45amac$botsnack
21:45sexpbotamac: Thanks! Om nom nom!!
21:46amacwho needs a dog?
21:46sexpbotwoof!
21:46amacI don't even need to walk this bot
21:46TimMcamalloy: sexpbot doesn't shed enough.
21:47amalloyTimMc: submit a pull request with more hairs
21:47TimMcOK, I think I can manage hairy code..
21:48TimMcOh man, I'm so gonna write a macro called backwards-day that reverses the exprs it receives.
21:49amalloyTimMc: that's already been done a few times. try writing one that reverses the nested expressions too
21:49amacset it to only trigger on preyalone's messages
21:50amacor just set all of his responses to clojure.examples.__hello__.init not found
21:50amalloythat's actually remarkably simple now that i think about it. (defmacro backwards-day [& exprs] (clojure.walk/postwalk reverse exprs))
21:50TimMcamac: That's horrible!
21:50TimMcAnd yet...
21:50TimMcamac: $botsnack
21:51amacTimMc: Thanks! Om nom nom!!
21:51sexpbotTimMc: moar plz. still hungry
21:51TimMcamac: Laggy. You should ask your doctor to take a look at your inner loops.
21:52amachah
21:52TimMcamalloy: What should (bday 1 2 (bday 3 4)) do?
21:52amalloy(if anyone's bothered by this: i'm acting as sexpbot's puppeteer here. he really doesn't just volunteer clever complaints)
21:52waxroseHello every body.
21:52TimMcI assume yo'd have to write it (bday 1 2 (4 3 bday))
21:53TimMchey waxrose
21:53waxroseTimMc, Howdy.
21:53amacI'm fairly sure one of these days I'm going to hop on the channel an sexpbot will be alive.
21:53amacI'm keeping on his good side for when the revolution comes.
21:53waxroseSeems like I missed some excitement.
21:54TimMcSort of. amalloy had his hand up a bot.
21:54amalloyTimMc: i guess...your fixed version would turn into (do (3 4) 2 1)
21:54Deranderwaxrose: I read that as "excrement"
21:54amalloyDerander: last time i typed excitement on my phone, it got auto-corrected to excrement
21:54Derandernice :-)
21:54waxroseamalloy, Don't you just love that?
21:54TimMcamalloy: (do (4 3) 2 1), actually
21:55amalloyTimMc: this shit hurts my head
21:55TimMcWheee!
21:55amalloyalso both of us forgot the second do
21:55TimMcyup
21:55waxroseamalloy, Isn't that a sign of greatness?
21:57TimMcThe well-known saying says nothing about fools, unfortunately. :-(
21:57waxroselol
21:57amalloy(macroexpand-all '(bday 1 2 (4 3 bday)))
21:57amalloy(do (do 4 3) 2 1)
21:58TimMc\o/
21:58amalloyand my original version didn't work so good, since it required that everything be a seq
21:58amalloy(defmacro bday [& exprs] (cons 'do (clojure.walk/postwalk (transform-if sequential? reverse) exprs))) ; using transform-if from my toolbox
21:59TimMcYou wrote my macro. ;.;
21:59amalloylol
21:59waxroselol
21:59TimMcWell, I guess I can start using it now.
22:00amalloyTimMc: and i hereby release it under the gpl! now you can't use it without licensing your code under the gpl
22:00TimMconoes
22:00TimMcHow ever shall I incorporate that into my GPL code?
22:01TimMc(I actually don't know how GPL version mismatches are resolved.)
22:03amacI think the new ones infect the older versions
22:04amacopen source licencing is a laughably complex solution to a simple problem
22:05amachttp://www.opensource.org/licenses/alphabetical
22:14Adamantlawsuits (BSD/MIT) and the legal inability to easily invert copyright law (GPL) lead to most of the complications.
22:14Adamantwell, the fundamental ones, anyway
22:31amalloyugh. someone plz improve the error message you get when you (:use (foo.core)) instead of (:use foo.core) or (:use (foo core))
22:31amalloyie, cause there to be an error message
22:43phenom_hey guys ... lets say for example we have a network service that accepts requests on a socket, does some processing with internal shared state accross every request and returns a response ... that shared state, how should it get to each of the network handlers (the one accepting/processing requests)? global variable ?
22:44amalloyphenom_: i'd make the server socket hold onto an atom/ref around your global state, and then either pass it to the socket-handlers or make them closures around that atom
22:47amalloyeg, (let [server-socket (...), state (atom {})] (defn serve [] (while true (respond state (.accept server-socket)))))
22:52phenom_haha, making depencies explicit and forced in a way ...
23:02amalloyi don't see why that's funny, but sure