#clojure logs

2011-02-04

00:27datkawhy does (first (map (fn [x] (println x) x) [1 2 3])) print all 3 numbers?
00:28brehautdatka: presumably chunked sequences
00:28brehautdatka: also, you can simplify that map to (map println [1 2 3])
00:29datkaI was trying to use filter identity and first to evaluate only the first element that returned non-nil, but it's doing too many
00:30datkaI wanted something that wouldn't retun nil
00:30brehautdatka: chunked sequences realise a small portion of the whole sequence to improve performance
00:30brehautif you realy only want to print the first item, how about (println (first [1 2 3]))
00:31datkathat was just an example, the actual function does a whole lot more
00:31brehautok sure
00:31brehauti have to go sorry
00:31datkaand I really don't want to process more than I have to
00:32brehautbut search about chunked sequences; i believe chris houser has a dechunkifiing function somewhere?
00:32datkaI will, thanks
00:32brehautsorry i cant be more help
00:33dnolendatka: or if you're building the sequence to be consumed, you can force it to be one at a time.
00:37datkacurrently, the sequence is a vector stored in a ref.
00:38dnolendatka: if it's a vector, then it's not actually going to 'process' more than you ask for.
00:38dnolendatka: what I mean if you're not doing sideeffects, does it matter? I suppose the operation you're doing is expensive?
00:39datkaactually, it looks like it's really the result of mapping over a vector
00:39datkaThere are some side effects (logging) and it's pretty expensive
00:40datkathink processing the routes for every page in an application on every request
00:43datkaI got it
00:46dnolen,(letfn [(lazier [l] (lazy-seq (cons (first l) (lazier (next l)))))]
00:46dnolen (first (map (fn [x] (println x) x) (lazier [1 2 3]))))
00:46clojurebotEOF while reading
00:46dnolen,(letfn [(lazier [l] (lazy-seq (cons (first l) (lazier (next l)))))] (first (map (fn [x] (println x) x) (lazier [1 2 3]))))
00:46clojurebot1
00:46clojurebot1
00:46dnolenis one way.
00:47dnolenprobably want to use recur there.
00:48dnolenheh getting late, it's lazy-seq don't need recur
00:48datkaget an error with recur
00:49datkaperfect. That did exactly what I wanted
00:51chouserhm, map doesn't support chunked seqs when given more than one collection
00:52zakwilsonWhat's the ETA on 1.3? Do most libs work with it yet?
00:54chouser,(letfn [(lazier [coll] (map (fn [x _] x) coll (range)))] (first (map prn (lazier [1 2 3]))))
00:54clojurebot1
00:55dnolenchouser: heh
00:55chousernot sure that's any better, though
00:55chouserin fact, I'm pretty sure mine's worse.
00:59dnolenzakwilson: none that I'm aware of but who knows, a lot of documentation needs to be written up.
01:15sritchieedw: hey, you don't happen to be a cascalog user, by any chance
01:16amalloychouser: isn't (fn [x & _] x) effectively (comp first list)?
01:17hiredman(fn [[x]] x) please
01:18hiredman(and preferably (comp first list))
01:26amalloyhiredman: i always feel devious when i do something like (fn [[x]])
01:27hiredmandeliciously devious
01:27amalloy*chuckle* yeah, some of that too
04:34neotykGood morning
04:35brehautmorning neotyk
04:44ejacksonhey gents.
04:46konrhello
05:01neotykin last talk by Stuart Halloway on InfoQ Clojure-Java Interop he mentioned some nice reflection/itrospection for Java classes, do you remember what was it?
05:24no_mindhow can I append values to a vector
05:24ejacksonconj
05:25raekno_mind: (conj [1 2 3] 4) (conj [1 2 3] 4 5) (into [1 2 3] [4 5])
05:25no_mindthnxs
05:31no_mindnot working... basically I want a function which returns a vector. The items of vector are generated with some logic. Any example of this ?
05:31ejackson(into [] (my-logic-generating-a-seq-of-values))
05:33no_mindejackson: what if I have a pre-defined vector to which I have to ad values. lets say (def vt [1 2]) . Now I want to add values to vt
05:33Chousukeyou can't change vt
05:33Chousukeyou can only create a new vector
05:33Chousukedesign your code so that that is not a problem :)
05:34no_mindk
05:34ejacksonyeah, so create a function that takes in vt as an argument, then conj's to it thereby creating a NEW vector which is returned by the function
05:34Chousukeif you really need state, you can use atoms or refs or agents
05:35Chousukebut *most* of your code should be stateless
05:35Chousukeif you have more than a couple refs, something is probably wrong
05:35Chousukeie, don't wrap a vector in ref just so you can mutate it
05:44no_mindChousuke: ejackson I am pulling some stuff from db and have to return it as json. The clj-json/generate-string requires a vector. What si teh best way to solve this
05:47ejacksonno_mind: this depends on a lot of stuff. I generally use read-json which takes the string that the db returns and returns an appropriate data structure.
05:47neotykno_mind: (into [] (map . .))
05:48no_mindthis is what I did (into [] (doseq [i (range 0 10)]{:name "test" :id i})
05:48no_mindbut not working
05:49Chousukedoseq is for side-effects
05:49no_mindk
05:49Chousukeyou want for, it generates a sequence
05:49Chousuke,(for [i (range 5)] (- i))
05:49clojurebot(0 -1 -2 -3 -4)
05:49neotyk,(doseq [i (range 0 10)] i)
05:49clojurebotnil
05:50Chousuke,(doseq [i (range 5)] (print i))
05:50clojurebot01234
05:50Chousukesee, side-effects only
05:51Chousukegenerally anything with a do-prefix is for side-effects
05:51Fossi,(print "foo")
05:51clojurebotfoo
05:51no_mindok
05:51Fossi,(print ",(print \"foo\")")
05:51clojurebot,(print "foo")
05:51Fossismart bot
05:51ejacksonno_mind: so just replace the doseq in your code with for, and it'll work
05:52no_mindk let me try
05:52Fossi,(print "/msg clojurebot ,(print \"foo\")")
05:52clojurebot/msg clojurebot ,(print "foo")
05:52ejacksonno_mind: you can also replace "into []" with plain "vec"
05:53no_mindk
05:53Fossifunky
05:53Fossi,(print "foo")
05:53clojurebotfoo
05:54Fossii guess clojurebot has been tested against a huge amount of attackvectors in the last year :D
05:59raek&(print ",(print \"foo\")")
05:59sexpbot⟹ ,(print "foo")nil
06:00raek,(print "&(print \"foo\")")
06:00clojurebot&(print "foo")
06:00sexpbot⟹ foonil
06:08zoldarhello; is there a way to pass arguments from vector while making an instance of a class? Something like (apply new clazz args) - this one does not work because "new" is a special form. Is there some way around?
06:10raekzoldar: you can wrap the constructor in a function if you know the number of arguments: (map #(Foo. %) [1 2 3])
06:11zoldarraek, won't it create 3 different instances ?
06:11raekzoldar: otherwise, you have to use reflection. clojure.lang.Reflector can help you with that.
06:11raekhttps://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Reflector.java
06:11raekyes, this was just an example of how you can make a constructor "function like"
06:12zoldarok, so it's not possible without ugly hacks
06:12raekbut I see that was not maybe what you needed
06:12raekno
06:12clgvzoldar: it's not an ugly hack to have a constructor method ;)
06:12clgvs/constructor/factory
06:12sexpbot<clgv> zoldar: it's not an ugly hack to have a factory method ;)
06:13zoldarok, thanks
06:14raekwhen the compiler sees (Foo. x), it will look up what constructors are avaiable and compile code that uses one of those
06:14raekif you want to choose which constructor to use (arity, signature types) at runtime, reflection is the only option
06:15zoldarunderstood
06:16raek(Reflector/invokeConstructor clazz (into-array args))
06:16zoldarwell, on the other hand, (defmacro make-instance [clazz & args] `(new ~clazz ~@args)) should also do the job in the end
06:17clgvzoldar: looks like it would ;)
06:17no_mindis there a package to read config file in clojure ?
06:17raekwell, you can't apply a macro, but for making the syntax prettier, yes. it would work.
06:18zoldarraek, crap, forgot about it
06:18zoldaranyways that's still some option
06:19raek,(fn [] (Integer. :foo :bar :baz))
06:19clojurebotjava.lang.IllegalArgumentException: No matching ctor found for class java.lang.Integer
06:20raekyeah, the constructor needs to be found at compile-time (when using new/Class.)
06:36zoldarso (clojure.lang.Reflector/invokeConstructor Integer (object-array [4])) is the way to go ?
06:43zoldarhttp://paste.lisp.org/display/119370 works ok; I wonder - is it so uncommon case that it's not in core? or is it something awfully bad to do in a way I'm missing?
06:53ChousukeI've never had need for anything like that :/
06:55zoldarok, it must be me then
06:55Chousukeit'd probably be a lot faster to just have a cond with different (Class. a b c) calls in each branch
06:56Chousukereflection is rather slow
06:56Chousukealso you don't need to name the parameter "clazz". class is just fine :)
06:56Chousukethe function is short enough that shadowing the class function does not matter.
06:58zoldarjust for the record, my use case for that: http://paste.lisp.org/display/119371
06:59zoldarChousuke, right, I've just seen "clazz" a couple of times when examining some libraries and took it as a some sort of convention
07:00Chousukeit's probably some java habit
07:00Chousukewhere class is a keyword that you can't use as a parameter
07:00Chousuke+name
07:02Chousukestyle nitpick: your (swap! regisrtry #(...)) thing is equivalent to (swap! registry assoc listener message)
07:02Dranikhi all!
07:03DranikI have just managed to create an example of how to automate java patterns implementation using clojure! Yahoooo! :-)
07:03zoldarChousuke, right, must have overlooked this, thanks
07:03Chousukezoldar: also, AFAIK the I prefix is generally not used with protocols.
07:03Chousukebut other than that, I guess what you're doing is fine :/
07:04zoldarChousuke: hmm, I guess I'm looking at the wrong code :) I recall seeing it in the joy of clojure
07:04Chousukeit doesn't look like you'll be creating very many of those listener instances
07:04Chousukehmm
07:04Chousukein Clojure itself I is used for interfaces.
07:05Chousukeand while protocols do generate an interface, it's more of an implementation detail
07:05zoldarChousuke, generally, there will be only one instance of ListenerRegistry, but I can't think of some better way of putting it together
07:06zoldaralthough, there may be at some point need for more than one registry
07:06Chousukealso do protocols even support varargs? :/ it might've been fixed but that wasn't the case last time I checked.
07:06zoldarwhat do you mean by varargs ?
07:06Chousuke& args
07:06sexpbotjava.lang.Exception: Unable to resolve symbol: args in this context
07:06Chousukesexpbot: :P
07:07zoldarhmm, I haven't tried it yet
07:08Chousukeyou might get weird behaviour
07:08Chousukesince & will actually get a parameter bound to it
07:08zoldarI'll fall back to a seq then
07:08Chousukeso your register method takes six parameters, including this :)
07:08zoldarnot too neat but still..
07:09zoldar5
07:09Chousukeno, I mean the way you've written it
07:09Chousuke_, owner, message, listener-class, &, and args :P
07:09zoldaraah
07:09zoldarnasty
07:10Chousukethe macro could probably warn about that :/
07:10zoldarcompiler could've warned about it
07:10Chousukeit seems to be a common mistake.
07:12zoldarI wonder - how clojure-in-clojure will cope with this whole interop mess? Will it be completely platform agnostic?
07:14Dranikzoldar, do you mean that somebody is developing clojure in clojure?
07:15zoldarDranik, umm don't current efforts go into that direction? beyond 1.3?
07:15zoldar*in
07:15Dranikzoldar, actually I don't know much about 1.3 that's why I'm so curious
07:16zoldarwell I'm not knowledgeable enough to give any details about this, that's just what I've heard/seen - maybe I was hallucinating ;)
07:17Dranikzoldar, :-)
07:17zoldarrandom search result: http://blog.n01se.net/?p=41
07:18Dranikzoldar, OK, we have to wait for rhikie and ask him. Guess, he knows...
07:20zoldarthere's even a bullet point under "Long-term" on http://clojure.org/todo
07:20Dranikbtw, how is ClojureCLR? Is it still alive?
07:20zoldarDranik: I can confirm that it is :)
07:20Dranik:-)
07:20zoldarhad opportunity to get in touch with dmiller
07:21zoldarthere was a bug in compilation procedure - he was very responsive
07:21zoldareven though the problem was messy, 3 days later the fix was there
07:21Dranikgreat!
07:22Dranikmay be one day I'll code Clojure in .NET!
07:23Dranikzoldar, seems like the day when Clojure will be as powerfull as CL is near...
07:23no_mindhow do I find value of a key form a hash-map
07:23Dranikpity, no reader macros in long terms...
07:24zoldarDranik, well, I'm not the one to judge about that ;)
07:24zoldarDranik - I thought that clojure actually has these already
07:24Dranikzoldar, its macrosystem lacks some points which CL has
07:24zoldarI confess, that I didn't try using these
07:25zoldarI talking about reader macros
07:25zoldar*I'm
07:27zoldarok, I was wrong, it's achieveable by some sort of hackery: http://briancarper.net/blog/449/
07:29Dranikzoldar, wow, that's great!!
07:31zoldar,({:a 1 :b 2} :a)
07:31clojurebot1
07:31zoldar<== no_mind
07:32zoldaror maybe I misunderstood
07:33no_mindzoldar: thanks, I figured that out :)
07:38ejacksonoh man, when it works, coding is such a rush !
07:40zoldarejackson, unfortunately for me it doesn't work more often than does, but that may be just sucky me
07:40ejacksonoh me either, but its those rare and precious times that make it worthwhile
09:02arnorhsIs clojure usable without contrib?
09:02jweiss_sure
09:02Dranikyep
09:03arnorhsbut isn't there a whole lot of stuff that relies on it?
09:03jweiss_any emacs user here able to tell me if I can get method signature in the repl for java method calls (in this case a constructor)
09:03jweiss_by repl i mean swank
09:03jweiss_slime, whatever
09:03Dranikarnorhs, so what's the problem? just add it to the classpath
09:03arnorhsno problem
09:04arnorhsi'm just wondering exactly what it's purpose is
09:04arnorhsi've always just installed it without thinking much about it
09:04Dranikarnorhs, it is "batteries"
09:04arnorhsisn't it a library?
09:04Vinzentjweiss_, if clojure, you can use smth like clojure.contrib.repl-utils/show
09:04Dranikyep, its a library
09:05arnorhsdoes eg. compojure rely on it?
09:05jweiss_Vinzent: i mean a builtin emacs function, to show the signature in the minibuffer space
09:05Dranikarnorhs, guess so, bcs contrib has lots of good stuff
09:05zoldaris there a way to avoid writing macro in case when the only thing i need is unquote splice (~@) operator ?
09:06Vinzentjweiss_, don't think that slime have java support
09:06pdkzoldar, apply
09:06zoldarisn't do a special form ?
09:06arnorhsI've just never thought much about it, I might start a new vm and see how far I can go without it
09:06pdk(apply + 1 2 [3 4 5]) -> (+ 1 2 3 4 5)
09:06zoldari mean (apply do body) instead of ~@body
09:07pdki don't see why you'd do it that way
09:07Dranikzoldar, write a macro which transforms your quoted code
09:07Dranikzoldar, sorry, not macro but a function
09:07arnorhswhat about the java build tools, ant & maven. Would most clojure apps work without them? Doesn't lein depend on those?
09:07Vinzentzoldar, you can use ` in fns
09:08pdk~ ` and ~@ can be used outside of macro definitions
09:08clojurebotmacro are just a game with symbols
09:08zoldarVinzent, ok I'll try
09:08pdkbasically anywhere you could use '
09:10zoldarok, got it, neat
09:17mattmitchellhow can i do a file path join?
09:18zoldarmattmitchell, clojure.contrib.duck-streams/file-str
09:18sgronbloAny vim users? Is there an easy way to get these rainbow parentheses and syntax highlighting without these slime-whatevers?
09:18mattmitchellzoldar: thanks!
09:18zoldarmattmitchell, but it seems to return java.io.File already
09:21fliebel$seen tonyl
09:21sexpbottonyl was last seen talking on #clojure 2 days and 16 hours ago.
09:23pdkeasiest way is probably just to intall vimclojure sgronblo
09:23fliebelpdk: easy? it took me hours to figure out all the conflicting instructions for the config and nailgun.
09:24pdki kinda gave up on the nailgun part of it too
09:24pdkthough if he just wants a more clojure friendly text editor the base plugin does the job
09:24sgronblopdk: but you can install vimclojure without bothering with this nailgun and stuff
09:24sgronblo?
09:24fliebelyou can
09:25pdki just ignored nailgun since i already had back luck trying to make emacs + slime work on windows
09:25pdkeither that or i'm that bad with emacs :p
09:25pdkbad luck even
09:25zoldarwhen I want to set an atoms contents to a completely new value, should I use reset! ? or are there cases where using (swap! foo #(fn [_] newval)) is preferred?
09:25pdkreset! is more concise
09:25pdkmaybe if the fns you're using to alter the atom are being generated on the fly
09:26fliebelzoldar: reset!, but if you wanted to do what you did, you'd use constantly.
09:26pdk,((constantly 1))
09:26clojurebot1
09:27zoldar(swap! foo constantly 1) ?
09:28fliebelzoldar: That would swap foo with a function that returns… the previsou valua and 1 or whatever.
09:28pdk(constantly x) is shorthand for creating a function that just returns the same x every time
09:28pdk,(constantly 1)
09:28fliebel&(swap! (atom 2) (constantly 1))
09:28sexpbot⟹ 1
09:28clojurebot#<core$constantly$fn__3551 clojure.core$constantly$fn__3551@223be4>
09:28pdk,#(1)
09:28clojurebot#<sandbox$eval108$fn__109 sandbox$eval108$fn__109@497536>
09:28zoldarok, it seems that it doesn't make sense anyway; I just recall someone somewhere advising for using swap! over reset! in some cases. I can't recall the detials
09:28zoldarok, got it
09:29pdkwe've seen a few insane suggestions from blog posts linked here before :p
09:29zoldarthat's why I'm asking - to set the record straight :)
09:29fliebelzoldar: If you look at the source, it uses atomicreference. swap uses compareAndSet, whule reset! just uses set.
09:30fliebelthis means that reset! will have a lot less overhead.
09:30pdkswap! is p much for making changes to the atom relative to its current value
09:30pdkthings like adding 1 to it etc, stuff where the original value is going to be an operand
09:31pdk,(let [x
09:31clojurebotEOF while reading
09:31pdk,(let [x (atom 1)] (swap! x inc) x)
09:31clojurebot#<Atom@d0005e: 2>
09:32zoldarI know, I just thought that maybe there's some merit to this, which I could be missing, like some marginal case in highly concurrent situations, but I see it isn't so
09:33fliebelzoldar: 2 paralel changes might leave behind a different result depending if you use swap or reset.
09:33zoldarfliebel, but it isn't predictable anyway
09:33fliebelwith reset, the last change wins, while with swap, the first retries.
09:40semperos_say I have a merge-with like this
09:40semperos_(merge-with (fn [v1 v2] (if (= "foo" v1) v1 v2)) m1 m2)
09:40semperos_how would I use that function within a (dosync (alter...)) ?
09:43semperos_I can understand the syntax for something like assoc-in, where the ref is the first param
09:43semperos_(dosync (alter my-ref assoc-in [:foo :bar] "baz"))
09:43jweiss_is there really no help from slime to see the method signature of a java class's constructor? do i have to open up the source?
09:44jweiss_for instance if i type "(String. "
09:44jweiss_and i want to see all the types the string constr will take?
09:45jweiss_i notice the inspector gives sigs but not for constructors
09:45jweiss_i was thinking more like the minibuffer with clojure fns
09:45jweiss_that shows what args it takes
09:45pjstadigjweiss_: patches welcome :)
09:46semperos_I don't know how, but considering java classes can have a whole bunch of constructors, I just keep the javadoc handy
09:46jweiss_hm ok. i'd love to submit a patch, but not sure if i'm up to the task. just wanted to check that it hasn't been done so i can stop searching google :)
09:52shortlordthere is nothing like a reverse operation of 'frequencies' built-in, is there?
09:53semperos_maybe a more general question is, how do I use functions with (alter) that take the value of the ref as the second param, instead of the first?
09:54fliebelshortlord: What would that do?
09:54shortlordfliebel: {:a 2, :b 1} -> (:a :a :b)
09:55fliebelshortlord: But maps are unordered… wel le me see...
09:55zoldarsemperos_ : (alter foo #(somefun arg1 %)) ?
09:56fliebel&(mapcat #(repeat (val %) (key %)) (frequencies [:a :b :c :b :c :c]))
09:56sexpbot⟹ (:a :b :b :c :c :c)
09:56semperos_zoldar: trying...
09:57fliebelshortlord: ^
09:57shortlordfliebel: yep, that's what I came up with as well, just wanted to make sure that there is nothing like that built in
09:58fliebelshortlord: I don't think so. Why would you need that?
10:00shortlordfliebel: well, the same question applies to frequencies, doesn't it? it's not too complex either, but is included in clojure.core. So I was wondering if something with the reverse effect was maybe included as well
10:01fliebelshortlord: Why do _you_ need it? I used frequencies a number of times, but never wondered if the opposite would be possible.
10:01semperos_zoldar: trying to use merge-with within (alter)
10:02semperos_(dosync (alter my-ref (fn [m] (merge-with my-func m another-m))))
10:02semperos_is what your suggestion looks like with that, but not working
10:02zoldaris another-m also a ref ?
10:02semperos_no, it's just a map
10:03semperos_plain (merge-with my-func m1 m2) works fine, with regular maps
10:03semperos_trying to get it right within a doref alter, because I want to use it with a ref
10:03semperos_*dosync alter
10:04shortlordfliebel: I guess I don't really need it. I wanted to figure out the total number of ordered things (the map stores ordered things + amount), but that could also be done using reduce
10:04zoldarsemperos_, what error do you get ?
10:04semperos_java.lang.String cannot be cast to java.util.Map
10:04shortlordif something like the reverse frequencies would have existed, I could have done (count (rev-frequencies map))
10:04semperos_stupid me
10:05semperos_thanks for asking that, made me look harder
10:05zoldarso probably ref is string
10:05semperos_nah
10:05zoldari mean contents
10:05bartjwhy is this an infinite loop ?
10:05semperos_another-m was a vector
10:05bartj, (doseq [i (range 10) j (range)] (println i j))
10:05zoldaruh
10:05fliebelshortlord: Ah, right. Yea, it seems all the data you might want out of the unfrequenced list is contained in the map.
10:05clojurebotExecution Timed Out
10:05semperos_I had used zipmap to create a new map from a couple of vectors
10:05semperos_was mistakenly passing in the old vector (instead of the new map from zipmap) as the second map
10:05semperos_thanks z
10:06semperos_thanks zoldar
10:06zoldarsemperos_, anyway you can use #(..) form instead of (fn [_] ...)
10:06semperos_yeah
10:06semperos_but I already had an anonymous function inside my merge-with
10:06semperos_was getting a bit hard to read :)
10:06zoldarah
10:06fliebelbartj: doseq loops the inner range first, which is infinite.
10:06bartjoh :(
10:06shortlordfliebel: yep, right now I am using (reduce #(+ %1 (val %2)) 0 map-with-products)
10:06bartjI'll just move it to the first then :)
10:06bartjfliebel, the same is with for, I guess
10:07fliebelbartj: doseq and for are nested, not parallel.
10:07bartjoh
10:07bartjdouble oh
10:07bartjhow can I iterate parallely, and then stop when one of them gets over ?
10:07fliebelsot i't go like 0,0 0,1 0,2 … 1,0 1,1 ...
10:07fliebelmap?
10:07clojurebotmap is lazy
10:07bartjyeah
10:07pdk(doc dorun)
10:07clojurebot"([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 successive nexts of the seq, does not retain the head and returns nil."
10:08pdk(doc doall)
10:08clojurebot"([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 successive nexts of the seq, retains the head and returns it, thus causing the entire seq to reside in memory at one time."
10:08fliebel&(map println [1 2 3] [4 5 6 7 8])
10:08sexpbot⟹ (1 42 5nil 3 6nil nil)
10:08pdkyou could iterate over the seq returned by map with doseq and execute the bulk of what you wanted to do each step in the body
10:09bartjyeah, I could do that
10:09fliebel&(map + [1 2 3] [4 5 6 7 8])
10:09sexpbot⟹ (5 7 9)
10:10bartjis there "no" way apart from a map ?
10:10fliebelloop/recur...
10:11bartjI am returning stuff lazily
10:11fliebelbartj: What is wrong with map?
10:11bartjand loop/recur will require me to artificially create a new variable and store stuff in it
10:14fliebelbartj: ^
10:14bartjfliebel, I am trying that
10:14fliebelok
10:14bartjfliebel, thank you for your time and answers
10:15fliebel:) have fun
10:24edwAnyone here use the ZeroMQ glue for Clojure? The destroy-socket fn throws an exception because there's no underlying destroy method on the Socket object. There is a close method. I do not have a lot of confidence is the clojure-zmq module, for this and other reasons...
10:42bartj,mail
10:42clojurebotjava.lang.Exception: Unable to resolve symbol: mail in this context
10:45bsteuberHi everyone
10:45Dranikbsteuber, hello!
10:45bsteuberdo you think it might be clever to make ^"foo" behave like ^{:doc "foo"} ?
10:46bsteuberseems reasonable to assume a string is mosten often used for documentation
10:48wolveriancd ..
10:48wolverianack.
10:49edwIs there a simple way to export constants in a namespace that are taken from a Java class?
10:51bartjedw, import-static ?
10:51bartjgrr, why does sexpbot say I have a message
10:51bartjand how do I view it ?
10:53edwbartj: Hmm. I need them to be public. I'll just ask people to also import the Java classes in their code.
10:59fliebelbartj: type $mail, and he'll show you.
10:59bartj$mail
11:00jweiss_is there a simple way to call a java method given a list of args, similar to using a apply on a clojure fn?
11:01bartjfliebel, thank you
11:01jweiss_,(apply System/getProperty ["a" "g"])
11:01clojurebotjava.lang.Exception: Unable to find static field: getProperty in class java.lang.System
11:01bartjlooks like someone sent me a mail
11:01bartjhow about sending someone an email here?
11:01bartjthat can be done using clojurebot ?
11:01raekjweiss_: clojure.lang.Reflector/invokeInstanceMethod
11:01raekhttps://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Reflector.java#L23
11:02jweiss_raek, what about static methods
11:02fliebel$mail bartj it is the same command.
11:02sexpbotMessage saved.
11:02raekbartj: $mail is a feature of sexpbot, not clojurebot
11:02jweiss_raek: ah looks like that's in there too
11:02raekyup
11:02bartj$mail
11:03bartjfliebel, cool
11:06raeklooks like there is a clojure.reflect.java namespace in 1.3. interesting.
11:07jweiss_,(clojure.lang.Reflector/invokeStaticMethod System "getProperty" ["a" "b"])
11:07clojurebotjava.lang.IllegalArgumentException: No matching method found: invokeStaticMethod
11:07jweiss_what's weird about this ^ is that the stack trace shows this exception is thrown BY invokeStaticMethod
11:07jweiss_i'd sorta understand if it said "no matching method: getProperty"
11:09raek,clojure.lang.Reflector
11:09clojurebotclojure.lang.Reflector
11:10raekjweiss_: I think you need to call invokeStaticMethod with an array
11:11jweiss_raek: ah right. still that error message sucks
11:11raekthere's also invokeStaticMehtodVariadic
11:12raekbut it's true... the reflector tried to find a suitable invokeStaticMethod method, but could not find any with a compatible type signature... ;-)
11:12raekin this case, that method is involved on two different levels
11:13mefesto,(clojure.lang.Reflector/invokeStaticMethod "java.lang.System" "getProperty" (into-array ["a" "b"]))
11:13clojurebotjava.security.AccessControlException: access denied (java.util.PropertyPermission a read)
11:13jweiss_mefesto: yeah i got it to work, i just don't understand how the call to public static Object invokeStaticMethod(Class c, String methodName, Object[] args) throws Exception
11:13jweiss_worked at all when i passed it a vector.
11:14jweiss_afaik a vector is not an array.
11:14jweiss_oh wait
11:14mefestoit worked with a vector?
11:14jweiss_no
11:14jweiss_but i thought the error message sounded wrong
11:15jweiss_but raek is right, the invokeStaticMethod was actually used to call itself.
11:15jweiss_the inner invocation is what failed
11:19jkdufairhow would i include a '.' in a GET request to a compojure route? I tried urlencoding it and also tried to read the clout src, but couldn't quite get it
11:19jkdufairi.e. http://localhost:8080/person/new/TheName/foo@bar.baz
11:20jkdufairit wants to treat the dot in the email as a separator
11:30Vinzentjkdufair, maybe "/person/new/:name/*"
11:30mattmitchellany opinions on clojure.test vs midje for testing?
11:30fbru02_mattmitchell: i use lazytest
11:30jkdufairVinzent: thx. I'll try that
11:32fliebelmattmitchell: have you considered clojure.core/test? < joke; I have no idea what the function is doing ##test
11:32fliebel&(doc test)
11:32sexpbot⟹ "([v]); test [v] finds fn at key :test in var metadata and calls it, presuming failure will throw exception"
11:34fliebelWhat is the difference between all those testing frameworks? I mean, you but a bunch of assertions in a file, and see if they work.
11:36semperos_fliebel: here's stuart sierra's thoughts on his work on clojure.test and then lazytest: http://stuartsierra.com/2010/07/05/lazytest-status-report
11:37semperos_he's blogged about it more than once, so that's one place to read
11:37jkdufairVinzent: worked! thank you. also makes me realize i need to understand defroutes even better
11:39Vinzentjkdufair, np :)
11:40edwIf you've written some simple glue to project foo, what should one call the code? clj-foo? clojure-foo?
11:43jkdufairlooks like a custom regex is my friend for this problem: ["/user/:id", :id #"[0-9]+"]
11:47Vinzentbtw, I have a trouble with appengine-magic. When saving new entity, I'm passing nil as a value of the key, and both save! and retrieve works fine, but key of retrieved entities still contains nil. Am I doing something wrong?
11:47Vinzentan example: http://paste.lisp.org/+2K2Q
11:50jkdufairI'm just letting appengine generate its own ids for me. perhaps try capturing the result of the save! shouldn't it provide you an id?
11:59Vinzentjkdufair, no, it's nil too. It's weird that I can retrieve entity by the key, so entity saved properly, but value of the key field in retrieved record not setted. Looks like a bug, isn't it?
12:00jkdufairVinzent: yeah it does, actually
12:01jkdufairdoes it happen in your local as well as at google?
12:02Vinzenthaven't tested it yet
12:04jkdufairi'll try it on mine and see if it's doing the same here
12:10Vinzentjkdufair, same thing with dev_appserver.sh
12:11jkdufairok. trying it out here
12:14jkdufairsame thing here. can retrieve by id, but the :id slot is nil
12:15jkdufairbtw, how do you run your tests using appengine-magic?
12:16Vinzent(use-fixtures :each (local-services)) just as sayed in readme
12:18jkdufairVinzent: thx. missed that one
12:48mduerksenhmm, when i defrecord with a field named size, odd things can happen (clj1.3): when retrieving field like this, everything is fine: (:size obj). but when retrieving the field directly, it returns the number of fields: (.size obj)
12:50amalloymduerksen: the . notation is overloaded between no-arg methods and fields
12:52mduerksenamalloy: shouldn't i be prevented from defining a record like this, or at least get a warning?
12:54amalloymduerksen: maybe. i thought i saw somewhere a mechanism for resolving the difference, but i can't find it anymore
12:55mduerksenok thanks amalloy. should i report this?
12:55amalloybut really i don't think you're supposed to be using (.field foo) notation for records anyway if you can help it
12:56mduerksenhmm, i like the . notation because its fast (and i need the speed in this case)
12:56amalloymduerksen: so is (:field foo)
12:57mduerksenoh, so (:field foo) uses the records accessor?
12:57amalloyif the record is type-hinted, the compiler will resolve it for you; even if it's not, i believe there's some call-site caching that optimizes into (.field foo) until such time as you pass in a different class
12:57mduerksenthat's interesting
13:00amalloymduerksen: hm, for a trivial microbenchmark it looks like i might be wrong. a type-hinted record :field takes ~300% as long as .field
13:00amalloyask hiredman though, he's always telling me how i'm wrong about records
13:01mduerksenwoah! when not type-hinted, (.field foo) is a magnitude *slower* than (:field foo) - i guess its because (.field foo) needs casting
13:01amalloymduerksen: it doesn't just need casting
13:01amalloyit needs reflection
13:01amalloyit's horrible
13:01mduerksenthanks, thats what i meant
13:02chousertype hinting won't help :field, I'm pretty sure.
13:03amalloybut yeah, mduerksen, it looks like hinted .foo is 3 times faster than :foo, which is...2000x faster than an unhinted .foo
13:03mduerksenmy microbenchmark looked like this: (defrecord Test [mine]) (def t (Test. 5)) (time (dotimes [n 1e6] (:mine t))) vs. (time (dotimes [n 1e6] (.mine t)))
13:03amalloyso you get most of the benefit just using :foo
13:04amalloymduerksen: yes, mine too
13:06mduerksenso it would be (.field foo) unhinted = 2000x (:field foo) = 6000x (.field foo) hinted. in that case, i will use (:field foo) normally and hinted (.field foo) in bottlenecks
13:07hiredmanbe sure not to just run it once for benchmarks, run it a few thousand times
13:08mduerksenhiredman: 1e6 should be enough to be stable
13:16mefestoanyone using clj-http ?
13:42brehautmefesto: yeah
13:51mefestobrehaut: im trying to fetch binary data from a url any tips?
13:51mefestobrehaut: seems like it keeps sending it to me as a string
13:52edwWhat does doing an HTTP HEAD on the URL return, content-type wise?
13:53mefestoedw: application/pdf
13:54edwHmm. What are you using to fetch the URL?
13:54mefesto(client/get url {:query-params {"id" "blah"}})
13:56mefestohoping for an input-stream like in clj-apache-http
13:56benreesmani appreciate this is sort of a weird question for this channel, but does anyone have a suggestion for which php web framework will be most comfortable for someone coming from a clojure mindset?
13:57edwWhy aren't you using clojure.contrib.http.agent?
13:58mefestoedw: no reason, just thought i'd give this lib a try
13:58brehautedw: if you are also using ring, clj-http is a good fit
13:58technomancyisn't contrib's http client deprecated?
13:59edwI'm not surprised that a random HTTP client library stringifies ecerything.
13:59brehautedw: ring is the clojure web dev / http stack
13:59mefestoit's also v0.1.3 so maybe this is a bug ... although this is my first crack as using it so it's more likely my fault
13:59brehautedw https://github.com/mmcgrana/ring
14:00edwAh. I hope to never write another web app again.
14:00mefestothat's one thing that made me look at clj-http since middleware in ring is so handy and clj-http uses the same design i believe
14:00brehautmefesto: it does
14:01brehautmefesto: the default clj-http.client/get etc wrap up a core api with a heap of common middlewares for you
14:01sritchiehas anyone here used leiningen with textmate?
14:02sritchieI use SLIME and emacs, but I need to ease a couple of guys into clojure, and they currently code in python, using textmate
14:02mefestobrehaut: just curious but is there an example of how one could wire up their own middleware into the request/response pipeline?
14:02sritchieany ideas on easing the learning curve?
14:02brehautmefesto: https://github.com/getwoven/clj-http/blob/master/src/clj_http/client.clj
14:02pdktextmate has a clojure plugin
14:02brehautmefesto: i think that page speaks for itself
14:02pdkfailing that eclipse/netbeans/intelliJ all have their own as well
14:02sritchiepdk: it looks good, for the syntax, it just uses cake
14:03sritchiepdk: sorry, I mean it uses cake, not leiningen
14:04brehautmefesto: i wonder if the wrap-output-coercion middleware is converting it to a string
14:04mefestobrehaut: so if i had my own middleware function (e.g. myns/wrap-custom) is there a way to get that into the chain? or do i have to update the client/request in a binding?
14:04brehautmefesto: if you pass :as :byte-array in your request options, does it work?
14:04brehautmefesto: make your own request, dont update the library binding
14:04mefestobrehaut: still a string
14:05brehautthats surprising
14:06mefestooh wait..
14:07mefestothat works... sorry, i put :as :byte-array in the wrong place
14:07mefestoclj-apache-http style :-\
14:07brehautah right. phew.
14:07mefestobrehaut: thanks for the help
14:08brehautmefesto: no worries. i just read the code ;)
14:16fliebelI'm looking to split a url of unlimited length into pairs into a map. Would it be best to write a quick string split directly onto Ring, or does one of those router libs offer this?
14:19fliebelso a/url/of/pairs -> ["a" "url" "of" "pairs"] -> {:a "url", :of, "pairs"}
14:23amalloy*baffled* what websites use the url that way instead of using ?query parameters?
14:23fliebelamalloy: wordpress?
14:24fliebelno, not exactly that way...
14:25fliebelthey do tag/blah or something similar. I want to extend that to multiple criteria.
14:28fliebelIs (apply array-map) a idiomatic way to turn a flat seq into a map? (into {}) expects pairs.
14:29chousersure, apply array-map or hash-map
14:30fliebelchouser: Thanks. Please remember me of the difference. Something with guaranteed order and small lenghts?
14:31fliebelI think someone told me before, but I can;t find it.
14:32technomancyfliebel: array-maps grow into hash-maps when they get large enough; array-maps preserve order
14:32technomancybut in general you shouldn't care about the distinction between the two
14:34amalloyfliebel: (into {} (partition 2 blah)) if you wanted to let the runtime figure out whether to use arrays or hashes
14:34fliebeltechnomancy: Interesting idea… Around what length? Are we talking around hundreds of items, or just anything larger than a shopping list?
14:35amalloyfliebel: ten
14:35amalloy&(class (into {} (partition 2 (range 8))))
14:35sexpbotjava.lang.ClassCastException: java.lang.Integer cannot be cast to java.util.Map$Entry
14:35fliebelamalloy: ten? not even 32? 32 is still the chunk size, is it?
14:35clojurebotamalloy: therfor I return [previous] if rest is empty
14:36fliebelamalloy: Same problem here ;)
14:36amalloyright, maps don't like seqs, they want vectors :P
14:36amalloy&(class (into {} (map vec (partition 2 (range 8)))))
14:36sexpbot⟹ clojure.lang.PersistentArrayMap
14:36amalloy&(class (into {} (map vec (partition 2 (range 22)))))
14:36sexpbot⟹ clojure.lang.PersistentHashMap
14:37fliebelnice
14:37fliebelbut, ugh, what a fuss to to get the map
14:37amalloyindeed. for urls, array-map is probably the way to go
14:37fliebelI figured so to.
14:37amalloyclojurebot: thanks for your suggestion, but as usual it is irrelevant
14:37clojurebotIk begrijp
14:37technomancyclojure will do the right thing either way
14:38amalloytechnomancy: ?
14:38fliebel&
14:38sexpbotjava.lang.Exception: EOF while reading
14:38fliebel&(class (apply array-map (range 1000)))
14:38sexpbot⟹ clojure.lang.PersistentArrayMap
14:39fliebelbut assoc-ing that returns a hash-map
14:39fliebelI'm going to stare at the implementation for a while, to figure out why there is this distinction.
14:40fliebelstatic final int HASHTABLE_THRESHOLD = 16
14:40jcromartieSo I've been reading Out of the Tar Pit.
14:41jcromartie(uh oh)
14:42semperos_using an atom to store a map; I run two swap!s, one after the other
14:42semperos_the first swap changes the value of a key in the map
14:43fliebelhm, array-map does what it says on the tin. a map backed by a plain old array. now, over to hash-map, to see why array-map is needed.
14:43semperos_the second does a merge-with to merge on a new map; the function passed to merge-with makes sure that, if a key has a particular value, it keeps that value instead of being replaced by the new map's
14:43semperos_when I do this step-by-step at teh repl, it works fine
14:43amalloyfliebel: a linear scan is faster than the hashing overhead for small-enough maps
14:44semperos_when I do it within a (let) in a function, it fails, the merge-with function doesn't do anything, a plain merge is performed
14:44semperos_any thoughts?
14:44mefestosemperos_: what if you combined both actions into a single function and just called that with swap! ?
14:44fliebelamalloy: I think you are right.
14:44raeksemperos_: can you post the code somewhere?
14:44amalloyfliebel: i know i am right :)
14:44semperos_I can
14:45semperos_mefesto: going to try your suggestion first
14:45jcromartieIt seems like Clojure draws a lot from "Tar Pit" but there are no libs for the declarative languages used to define state, logic, and accidental useful state or control
14:46fliebelamalloy: I meant to say I was not even going to doubt it, the source code looks long, complicated, and mentions papers.
14:46raekif you want to keep the old values, can't you just do (merge new-map old-map)?
14:47semperos_raek: yes, actually; I was caught up thinking about the fact that swap! and friends all take the derefed value as a first argument
14:47semperos_but I can just use an anon fn and move it
14:47semperos_raek: thanks
14:47semperos_still curious why merge-with wasn't working though
14:48raek(swap! a #(merge %2 %1) m) (swap! a #(merge % m)) (swap! a (partial merge m))
14:48semperos_yep
14:48semperos_needed fresh eyes, thanks
14:50jaskirathey guys, i have been trying to understand recursive macros with this exaple in the practical clojjure book, but i cant seem to get it right.
14:51raekmacros where the expansion contains the macro symbol?
14:51jaskirati am trying to write a simpe macro to convert (++ 1 2 3 4) to (+ 1 (+ 2 (+ 3 4)))
14:51jaskiratcan you help me point out why this doesnt work
14:51jaskirat(defmacro ++ [& e] (if (>= 2 (count e)) `(+ ~@e) `(+ ~@(first e) (++ ~@(rest e)))))
14:51amalloyjaskirat: macros are really just functions that operate on, and return, lists
14:51jaskiratyep
14:52fliebeljaskirat: Have a look at the source of -> for inspiration.
14:52jaskiratoops
14:52jaskirat(defmacro ++ [& e] (if (>= 2 (count e)) `(+ ~@e) `(+ ~@(first e) (++ ~@(rest e)))))
14:52jaskiratlinks?
14:52raekso you want (++ 1 2 3 4) to expand into (+ 1 (++ 2 3 4)) and then into (+ 1 (+ 2 (++ 3 4))) and so on?
14:53amalloy$source ->
14:53sexpbot-> is http://is.gd/KrdckN
14:53jaskiratraek: yes
14:53jaskiratamalloy: thanks
14:53raekjaskirat: have you used macroexpand-1 ?
14:54raekit's very useful for seing what your macro actually does
14:54jaskiratraek: yep it runs into a Don't know how to create ISeq from: java.lang.Integer
14:54raekjaskirat: I think ~@(first e) should be ~(first e)
14:55jaskiratraek: oh yeah ! because first doesnt return a list
14:55jaskiratraek: let me try!
14:55mattmitchelli have a quoted list like: '(double :key) and i'd like to grab the :key keyword, use it as a key on a hash that contains a number, and then apply it to double. How do I "eval" or execute double (the function) from a quoted form?
14:55amalloy&(reduce (partial list `+) [1 2 3 4])
14:55sexpbot⟹ (clojure.core/+ (clojure.core/+ (clojure.core/+ 1 2) 3) 4)
14:56jaskiratraek: awesome :)
14:56jaskiratraek: thanks a lot
14:56fliebelamalloy: Nice one :)
14:56mattmitchelli found that eval works, but is that the right way?
14:56amalloyjaskirat: my version expands in the opposite direction, but you might find it useful
14:56raekmattmitchell: you could do something like [double :key] or (list double :key)
14:57jaskiratamalloy: thanks , i was just learning about macros and trying em out
14:57raekthen you will have the double function as the first element, rather than the symbol 'double
14:57amalloymattmitchell: you'll need to eval if it's in a quoted list. is there a reason you can't have [double :key] instead, storing the actual function "double"?
14:58mattmitchellamalloy raek: ahh ok. no, i didn't think about doing it like that.
14:58raekmattmitchell: it's not very common to need to use eval (in my experience). most of the time, there is a more simple way
14:58mattmitchellraek: ok good then. my instincts were on to something.
14:59raek,(let [pair [double :a], m {:a 1, :b 2}] (let [[f k] pair] (f (get m k))))
15:00clojurebot1.0
15:01amalloyjaskirat: for sure, it's just good to keep in mind that you can write macros with list-manipulation functions as well as syntax-quote, especially when the latter will look convoluted
15:03jaskiratamalloy: i am very new to clojure, so i am not really aware of all list manipulation functions as of yet. That was new to me.
15:04amalloyjaskirat: there are a lot of such functions; it takes a lot of time to know "all" of them. but reduce, map, and iterate will get you most of the way
15:04jaskiratamalloy: that example that i was trying to solve was straight out of "practical clojure" and was wrong in the book but i could not figure out the bug
15:05fliebelHm, I'm planning to do a XML DSL tomorrow. Core idea is that tags are lists with :namespaced/keywords and metadata. It'll be implemented on top of SAX. If you have ideas to share or want to nudge me into the right/a more sane direction, now is the time :)
15:07jaskiratamalloy: actually i was aware of map / reduce but your combination of partial along with this was particularly new.
15:07amalloyjaskirat: yeah, partial is crazy
15:08fliebelamalloy: Why and when do you use partial over an anonymous function? I like partial, but I had some discussions with people who prefer @() at all times.
15:08fliebel#() I mean
15:09amalloyfliebel: meh. you can't nest #()
15:09amalloypartial is overly verbose and prone to abuse, so i don't use it too often, but it seemed appropriate here
15:10amalloyi could have written instead ##(reduce #(list '+ %2 %1) [1 2 3 4]) and gotten the expansion order right, i think
15:10sexpbot⟹ (+ 4 (+ 3 (+ 2 1)))
15:10fliebelamalloy: What abuse?
15:12mattmitchellhow do you test whether or not something is a function? etc.. (function? (fn [])) => true
15:12amalloymattmitchell: fn? or ifn?
15:12amalloyfliebel: if you start writing things like (map (partial map (partial apply +) ...)) your code gets to be unreadable
15:12mattmitchellamalloy: arg sorry :) i tried fun? func? and function? but not fn?
15:12fliebelmattmitchell: Beware of ifn though ##(ifn :a)
15:12sexpbotjava.lang.Exception: Unable to resolve symbol: ifn in this context
15:13fliebel&(ifn? :a)
15:13sexpbot⟹ true
15:13amalloybetter to break it up into a couple explicit functions
15:14amalloy$findfn first true
15:14sexpbotjava.lang.Exception: Unreadable form
15:14amalloy*blink*
15:14amalloywell, bugger that, i guess i have some debugging to do
15:14fliebelwhat would that do?
15:14amalloyfliebel: search for functions that return true when called on clojure.core/first
15:15fliebelamalloy: Does it do some clerer introspection, or does it try 500 functions to find ones that return true?
15:15amalloythe latter
15:15fliebelexpensive...
15:15amalloyfliebel: not really
15:16amalloy$findfn [1 2 4 8] [8 4 2 1]
15:16sexpbot[clojure.core/rseq clojure.core/reverse]
15:16fliebelneat!
15:16amalloysee? takes less than a second, when it's not broken :P
15:17sgronbloheh thats pretty cool
15:17fliebelSo next time I have someone ask for a function that transforms x into y, I can let sexpbot figure that out.
15:17fliebelamalloy: Does it work for multiple arguments?
15:17amalloyfliebel: indeed, but it's still pretty limited. it won't find partition for turning a list into a group of pairs, because it needs an additional 2
15:18amalloy$findfn 1 2 3 6
15:18sexpbot[clojure.core/+ clojure.core/*]
15:19jaskirat$findfn [1 2 3] 6
15:19sexpbot[]
15:19fliebelamalloy: Yea, so it's limited to 1:1 matches, not the slightest fiddling.
15:19amalloyfliebel: yeah. i've pondered improving it somehow, but nothing seems clear or easy
15:20jaskirat$findfn [1 2 3] [6]
15:20sexpbot[]
15:21fliebel$findfn + [1 2 3] 6
15:21sexpbotjava.lang.Exception: Unreadable form
15:21fliebelhrm...
15:21amalloyfliebel: i think it doesn't like functions
15:22amalloyand i think i know why too; i'll poke around at it
15:22fliebel$findfn #(+ %1 %2) [1 2 3] 6
15:22sexpbotjava.lang.Exception: Unreadable form
15:22Rayneschouser: ping
15:23amalloyfliebel: if we're going to be spamming with sexpbot we should do it in #sexpbot
15:37defnany sign of stuart halloway's talk at clojure conj?
15:39chouserRaynes: pong
15:43defnyay for an activerecord-esque lib for clojure
15:44Rayneschouser: I've not yet been told how No Starch chooses tech reviewers, but the editor mentioned it, so I pointed out that you would be a good option if you were interested. Just thought I'd ask if you are and if so, if you could give me an email address to pass along, assuming they take my advice.
15:44RaynesNo pressure to do so. You were just the first person that came to mind.
15:48chouserRaynes: to review your book?
15:48RaynesRight.
15:48RaynesThey need a "hardcore Clojure guy".
15:48RaynesI'm not sure if they pay reviewers, but they probably do.
15:49RaynesAt least, O'Reilly does.
15:50chouserRaynes: I use gmail -- you can guess my username. I'd like to know how long it is and when I would be able to start.
15:52Rayneschouser: I doubt the book will ever surpass 300 pages. The current draft is around 150 pages. At least, it is with my formatting. No clue what it'll be when they do whatever they do with it. I'll pass along your email address, and if he is interested, I'm sure he'll fill you in more throughly.
15:53chouserRaynes: thanks.
15:58TobiasRaederhi :)
15:59TobiasRaedercan anyone explain to me when someone would use comp instead of ->/->>? comp seems to do the same (atleast to me)
15:59chouser-> and ->> are macros. comp is a function.
15:59amalloyTobiasRaeder: comp is a function, -> are macros
15:59TobiasRaedergood point :)
15:59amalloychouser: that's what i get for pausing to confirm before i hit enter
16:00chouserheh
16:00chouserTobiasRaeder: http://blog.fogus.me/2010/09/28/thrush-in-clojure-redux/
16:00amalloyTobiasRaeder: eg, (map (comp square inc) (range)) is hange
16:00amalloyhande
16:00amalloyhandy. damn it
16:00fliebelAnd… comp can't take extra arguments, unless with #(), right?
16:01amalloyfliebel: shhhhh, you'll awaken a monad evangelist
16:01TobiasRaeder:D thanks for the infos
16:02sgronblome too
16:03amalloythey're generalizations at a level more abstract than function composition. i still haven't gotten my head around when they would be useful in my code
16:03amalloyyou can find a zillion tutorials of varying quality online
16:03hiredmana monad can be deconstructed into a protocol for passing arguments between functions and a protocol for binding names to values (which are really the same thing)
16:04fliebelYea, there are to much monad tutorials out there. Maybe I should write one.
16:04ChousukeI wrote a toy protocol based monad interface once I think it's still somewhere on the internet :P
16:04Chousuke+.
16:05amalloyfliebel: nah. they're just like burritos
16:05amalloy$google monads are like burritos
16:05sexpbotFirst out of 252 results is: The Universe of Discourse : Monads are like burritos
16:05sexpbothttp://blog.plover.com/prog/burritos.html
16:05amalloyfliebel: mexican food. tacos
16:06fliebeloh, well, second paragraph, and he used another word I don;t know LO
16:06fliebel(I need to stretch my fingers more when I reach to the right)
16:07amalloyfacetious ~= joking
16:08fliebelamalloy: I was talking about functor
16:08amalloyfliebel: man, that's like the *third* paragraph
16:08fliebelamalloy: Dude, zero-indexed, you know ;)
16:13jcromartieDon't blubify Clojure by saying that you couldn't imagine why monads are useful :)
16:14LauJensenMorning guys
16:16TobiasRaederhey lau :)
16:16LauJensenhey Tobias
16:16fliebelhey
16:18fliebelLauJensen: How vulnerable is CQL to SQL injection? Are all strings I use escaped, or ca I use literal SQL in there?
16:18LauJensenfliebel: ClojureQL keeps you 100% safe. It automatically parameterizes all queries
16:18fliebelgood :)
16:19fliebelI asume there is a function for weird cases where you need real sql?
16:19LauJensenfliebel: Whereever possible I support literal strings, but if you need some really funky SQL, you need to submit a compiler for that backend
16:20LauJensenBut it really does do most things
16:21fliebelokay :) I don't expect to encounter any of those cases with my limited sql knowledge. I have been meaning to try cql for a while now, but haven't done so yet. :(
16:23LauJensenI regularily get emails from people telling me how much they love it, so I assume its good :)
16:23fliebel:)
16:44dnolenI see two problems now w/ monads 1) not particularly efficient 2) inherently single-threaded. 1) seems like a hard problem to solve in the general case 2) can't do anything about that
16:51Chousukednolen: both 1 and 2 are false, unless you're talking about a specific implementation
16:52Chousukeany monad is free to combine operations in whichever manner it's programmed to do, and that includes running the ops in parallel.
16:53Chousukeat least, as far as I can tell, I'm not a monad expert either. :/
16:54hiredmanthe new composable async Task stuff in C# and VB.Net is built on a monadic interface
16:55brehautpoint #2 is one rhickey has made before
16:56hiredmanwell, that is not correct
16:56brehauthttp://clojure-log.n01se.net/date/2010-02-12.html#i70
16:57hiredmanwhats the link for?
16:57brehautthats the previous discussion on the same
16:58hiredmanif you are trying to convince me that rhickey said it, I believe you, but just because he said it, that does not make it correct
16:59brehautof course it doesnt
16:59hiredmanhttps://github.com/hiredman/die-geister is my take on the async Task stuff from C#
16:59hiredman(also F# has async too)
17:00brehautF#'s async is great
17:01hiredmanright, the reason you can compose async tasks is Task is a monad
17:01brehautyes.
17:01hiredman(I think the f# paper on them calls them joinads)
17:05brehautamalloy: monads are more about generalised function application than composition; arrows are the generalised composition
17:06opqdonutisn
17:06opqdonut't Applicative generalised function application?
17:06brehautdepends how far you want to generalise
17:06opqdonutmhmm
17:06hiredmanhttps://github.com/jduey/conduit
17:07opqdonutoh, this was #clojure
17:07opqdonutthought for a moment I was in #haskell
17:07hiredman:D
17:08brehautits the armchair categorists meetup today
17:08hiredman(conduit is built on arrows)
17:09brehautfrightening and awesome :)
17:09hiredmanwe use it at work for our async messaging
17:09hiredmanactually clojurebot uses it now too
17:10hiredmanfor streaming processing in clojurebot's case, not async messaging
17:17brehauti dont know how i missed jim duey's stream articles
17:17brehautthey are really good
17:24dnolenhttp://www.mail-archive.com/haskell-cafe@haskell.org/msg71116.html
17:24dnolenmonads are sequenced, not commutative.
17:26dnolenhttp://www.valuedlessons.com/2008/03/why-are-my-monads-so-slow.html
17:26hiredmandnolen: if I disgree more, will you spend more time googling about it?
17:27dnolenhiredman: why google when you can point me to better articles?
17:28hiredmandnolen: why would I do that?
17:29dnolenasync ops still implied explicit sequencing, and that not a general concurrent framework anyhow.
17:29dnolenor rather it has a lot of assumptions about ho to solve the problem right?
17:30hiredmanif you look at die-geister it allows you to join multiple async tasks into a single async task
17:30hiredmanwhile not explicitly a monad the implementation is very similar to something like, uh, whats it called, fmap? for the list monad
17:30brehautfunctor
17:32dnolenfor example commute in Clojure's STM is an interesting solution to some problems, a monad can't capture that as far as I can tell.
17:33hiredmancommute is not functional, why would you want to use that in a functional construct like a monad?
17:36dnolenhiredman: except people use monads to model state
17:36hiredmandnolen: they use monads to model state in a functional setting
17:37hiredmanrefs are mutable and not functional, so why would you do that?
17:37Chousukestate is not all monads are good for.
17:37dnolenChousuke: I know that.
17:37hiredman(actually haskell's STM is exposed in a monad because they hide all mutable things in monads)
17:40brehauthiredman: i think geister might be closer to an applicative than functor?
17:40dnolenhttp://www.mail-archive.com/haskell-cafe@haskell.org/msg82109.html
17:41hiredmanbrehaut: *shrug*
17:41dnolenin anycase, monads - big tradeoffs as with all things.
17:42brehautthe difference is that as well as being able to apply functions to thinks in the async context, it also has a way to apply functions that are in async contexts to other async contexts resulting in a new async context?
17:42hiredmandnolen: the issue there is the haskell type system doesn't express the constraits of being communicative
17:42hiredmanbrehaut: that is ultimately bind
17:43hiredmanbind is like a protocol for binding names to values
17:43brehauthiredman: its slightly less than bind i thing
17:43hiredmanit is less then bind because I can't enforce the type
17:43brehauthiredman: in haskell applicative is also less than bind even though they can enforce type
17:44hiredmanI see
17:44hiredmanbut I want to enforce the type
17:44hiredmanI just can't
17:44brehautthe type of yeh applicative operator (<*>) is f (a -> b) -> f a -> f b
17:44brehautvs bind which is m a -> (a -> m b) -> m b
17:45hiredmanif you are looking at the die-geister source I am very proud of blet and Bindable
17:45hiredmanrealizing I could do that as a protocol was so cool
17:45brehauti am and agreed
17:45brehauti liek the extension of deref to bindable too
17:46brehauti cant find blet though
17:46hiredmanmaybe I never commited it
17:47hiredmanit's a macro that expands to a let that calls bind on everything before binding it to a name
17:48hiredman(with the default extension of Bindable to Object being identity)
17:48dnolenmy miniKanren work also made me suspect things like this - http://www.haskell.org/haskellwiki/Performance/Monads
17:48dnolenunrolling monads
17:49brehautdnolen: even simple state-m definitions explode into frightening amounts of funcalling; adding any transformers on top is even more horrific
17:50hiredmanI am by no means advocating monads everywhere, I am just saying they are extremely useful as a basis for library writers to ensure the composability of their code
17:50hiredmanand that monads do not imply single threads of execution
17:57brehauthiredman: re: applicitve and monad, i think monadic for can be defined for any applicative in terms as a >>= f = (pure f) <*> a.
17:57brehautwhich muddies the waters between applicative and monad even more
17:57brehaut(pure being the applicative function to take something and put it into the appropriate applicative type0
19:53sritchiedoes anyone have any advice on how to encode a float array as a byte array?
19:54sritchieI can map the array to a seq -- I'm just not sure how to get a byte representation of my float, for the map
20:04amalloysritchie: make a ByteArrayOutputStream, wrap it in a DataOutput, write floats to it, then read them as bytes; or do the equivalent with buffers
20:04amalloywould be my hacky solution
20:04sritchieamalloy: this is sort of a hack, in any case -- hadoop can stream byte arrays, but not float arrays
20:05sritchieamalloy: I'll go check out io for outputstream
20:06amalloyi don't think c.j.io will have the necessary tools, you'll have to actually use java.io.XXX stuff
20:06sritchieamalloy: yeah, looks like it
20:06sritchieamalloy: it's odd, I'm searching all over, and this doesn't seem to be something anyone's been vocal about yet
20:07sritchiepassing anything but byte arrays or heavy custom objects around
20:07sritchieor maybe it's considered trivial, who knows
20:07amalloysritchie: hadoop will handle floats for you, won't it?
20:08sritchieamalloy: yes, but not float arrays
20:08sritchieamalloy: byte arrays can be wrapped in BytesWritable quite easily,
20:08amalloybut the underlying hadoop model is that most parts of the system deal with "data" they don't know anything about, which is what BytesWritable is for
20:08amalloy"here is a chunk of data, sritchie plz deal with it cause it is too confusing for the hadoop internals"
20:10sritchieamalloy: yeah, that's true - I do that for an inputformat I wrote that takes a single file at a time, rather than cutting text into lines, etc
20:10sritchieby opening a stream, and using IOUtils.readFully
20:11sritchieamalloy: so it sounds like your suggestion is the way to go, just copying that approach by streaming out these floats
20:12sritchieamalloy: that's hadoop's IOUtils, btw
20:13amalloysritchie: hadoop's, or apache commons? it surprises me that hadoop would expose a way to read a file fully, with its "big data" approach
20:13sritchiehadoop's, actually -- http://bit.ly/h1JYXT
20:13amalloyfair enough
20:38sritchieamalloy_: so it looks like cascading does support byte arrays natively -- one just has to add the serialization beforehand
20:38sritchienow, I just need to find out how to do that in cascalog
21:28joshua__$findfn nil false
21:28sexpbot[clojure.core/keyword? clojure.core/chunked-seq? clojure.core/sequential? clojure.core/fn? clojure.core/not= clojure.core/string? clojure.core/sorted? clojure.core/false? clojure.core/true? clojure.core/symbol? clojure.core/number? clojure.core/integer? clojure.core/... http://gist.github.com/812141
22:24trptcolinso i'm teaching a clojure course in april - geared more towards the beginner end of the spectrum than most in the #clojure irc crowd
22:24trptcolinany tips on promotion?
22:26trptcolindetails: http://8thlight.com/courses/2-clojure-functional-programming-on-the-jvm
22:29amalloytrptcolin: i wrote a blog post with that target audience last month; you might find some stuff you can use at http://hubpages.com/hub/What-is-Clojure
22:30trptcolinnice, that looks great!
22:31amalloytrptcolin: go spread links all over the internet; my coworker (at hubpages) needs to be constantly reminded that clojure generates more traffic than his silly hobbies :)
22:31trptcolini do think i have a decent approach/handle on getting the material across once in the class, it's mostly getting people *to* the class i'm unsure about
22:32trptcolingood point. i don't want to come across as spammy though
22:32amalloytrptcolin: i kid, i kid. don't spam me
22:32amalloyor for me, rather
22:32trptcolinLOL
22:34brehauttrptcolin: just stay clear of fact and fib ;)
22:35trptcolinwhat? but how will i teach the joys of avoiding StackOverflowError ;)
22:36brehauthaha
22:36amalloybrehaut: haskell has spoiled you so much that you don't think (defn ! [n] (reduce * (range 1 (inc n)))) is elegant?
22:37brehautamalloy: i love a good hylomorphism as much as the next nerd, but i dot think FP noobs care :P
22:37amalloyaha. yes, that is certainly true
22:37trptcolinoh snap you brought out the *morphism in #clojure
22:37amalloylol
22:37brehautit was worse earlier
22:38amalloytrptcolin: brehaut is from the wrong side of the tracks
22:38brehautthere was a spontaneous meeting of the armchair categorists
22:38brehautyeah python and javascript ;)
22:39brehautamalloy: also, you can hardly talk. all that point free? thats certainly from the dark side ;)
22:44brehautamalloy: talking of point free, have you looked at conduit ?
22:45amalloybrehaut: i caught a link to it from twitter on the bus ride home, but barely glanced at it. the readme isn't very compelling :P
22:45brehauthah
22:46brehautits comp and juxt souped up with nos and a rocket booster
22:57amalloybrehaut: you should see the absolutely disgusting parsing functions i wrote for my markov bot. i really need to learn fnparse or parsec or something
22:57brehautyou absolutely do. parsec is the most elegant but fnparse looks solid
22:58brehauti wrote a parser combinator library for python (its easy to write excruciatingly slow parser) and it made a bunch of day to day tasks a world easier
23:00brehautneed to find the time to learn fn-parse myself
23:16amalloybrehaut: when you do, please write up some cliff notes for me
23:16brehautsure thing :)
23:16amalloycause you're clearly my secretary
23:16brehautclearly
23:17brehautit'll makea good blog post anyways