#clojure logs

2012-01-21

00:00jeremyheilerbrehaut: nice, yeah
00:06technomancyjeremyheiler: it's only like a hundred lines
00:10technomancyI think it's been spun off without a proper maintainer anyway, since the chances of further changes to it are so slim
00:13jeremyheilertechnomancy: yeah, im not saying it's difficult to reproduce or anything. my thought was that this stuff was maintained in clojure proper, then it would be easier for libraries to depend on network io code and still be cross platform. im not sure if that's a real goal, though.
00:16clj_newbI have a [1.0 2.0] in clojure land. A Java function requires a float []. How do I convert it to a float [] ?
00:17jeremyheiler,(float-array 2 [1.0 2.0])
00:17clojurebot#<float[] [F@1e21544>
00:17jeremyheiler,(float-array [1.0 2.0])
00:17clojurebot#<float[] [F@4c638b>
00:18clj_newbjeremyheiler: worked; thanks.
00:18jeremyheilernp
00:18clj_newbbtw, what is to-array used for?
00:18clj_newbI dug to-array up, it didn't work; and now, I'm not sure when to-array is ever useful
00:18technomancyjeremyheiler: the question of who maintains a library doesn't really affect how easy it is to depend upon
00:19technomancyunless you mean the question of how easy it is to discover
00:19jeremyheilerclj_new: to-array returns an array of objects instead of primitives
00:20clj_newbjeremyheiler: Object[] rather than float[] ?
00:20jeremyheilerclj_newb: yeah
00:21clj_newbunderstood; thanks
00:23jeremyheilertechnomancy: i meant if i were creating a clojure library that i wanted to work on both the jvm and clr, having something as basic as net io bundled with the langauge would make developing and distributing the library easier.
00:25technomancyah, inside clojure.jar itself? yes, that's different.
00:25technomancyand very rare
00:28jeremyheileryeah, and it's understandable since interop is so simple.
00:46muhoowhat does ^: mean, as in (def ^:dynamic *group* []) ?
00:46muhooi know what :foo is, but what is ^:foo ?
00:47oakwiseis anyone using lein-cljsbuild?
00:48jeremyheilermuhoo: it's the same as saying (meta :foo)
00:48muhooah, thanks
00:49muhooone more thing i couldn't easily search for in the language reference:
00:49muhoowhat is #(), as in #(str %1 "-" %2) ?
00:50jeremyheiler#() is an anonymous function. it's the same as saying (fn [a b] (str a "-" b))
00:51muhoothanks!
00:52Raynes&(meta :foo)
00:52lazybot⇒ nil
00:52RaynesThat is not the same.
00:53RaynesIt is the same as saying (def ^{:dynamic true} *group* []), which sets the metadata for the *group* bar to the map you see there, containing :dynamic true.
00:57muhooso, um, #^{:foo "bar"} is the metadata of an anonymous function?
00:58muhoothat one has me stumped
00:59RaynesNo.
01:02brehaut^ is reader metadata, so its on the form, not the result
01:02brehautwith-meta is how you apply metadata to runtime data
01:04clj_newbis there a way in java/awt to have the awt application treat Tab as a modifier key?
01:14franksany "easy" way to find the process id of your clojure program?
01:24muhoofranks: ps fax |grep java ?
01:25franksmuhoo: understood, but now from within your running clojure program...
01:26technomancyfranks: I think you can use JMX; it's of obtuse IIRC
01:30franks(println "PID:" (:out (clojure.java.shell/sh "bash" "-c" (str "echo -n ${PPID}"))))
01:30franksough...
01:30muhooso what's the difference between #{:foo, :bar} and {:foo, :bar} ?
01:36duck1123muhoo: #{:foo :bar} is a set containing 2 items
01:36duck1123the other is a hashmap with 1 pair
03:25muhoocool. so then what is #^{:foo "bar"} ? a set that is metadata?
06:58jondot1hey guys. without going into editor wars, what editor is most suitable for clojure? (when i did scheme 6 years ago, i used to use emacs)
07:02raekI don't think you can determine which one's the "most suitable" without going into editor wars
07:04raekI use emacs myself. clojure-mode has very good Leiningen integration.
07:05jondot1well, i'd use emacs as well, just there is a new variable here that i don't really know how to handle - java integration
07:06raekalso, according to this survey emacs+slime is used by 61%: http://cemerick.com/2011/07/11/results-of-the-2011-state-of-clojure-survey/
07:07raekjondot1: you have a Clojure project that needs to interoperate with a Java project? or do you just need to use Java libraries?
07:07jondot1mostly, using java libraries for NLP.
07:08jondot1i guess clojure would be the glue language in this case
07:09raekok. the project and library stuff is handled by Leiningen. An IDE that strictly builds on top of Leiningen for its Clojure project support (like Emacs) does not have to deal with these things at all
07:10raekjondot1: have you looked at Leiningen?
07:10jondot1not really, i have a long list of tabs which i have to read serially about clojure :)
07:10jondot1i'll change the order i guess.
07:10raekconsuming a Java library is very simple if it exists in the maven central repo
07:11raekjondot1: good! the lein tutorial should be very high on the list, IMO. https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md
07:12jondot1great, thanks!
07:12raekjondot1: since you're interested in java libs I might as well point you to a search engine: http://jarvana.com/jarvana/
07:13raekyou usually find Java libs there and Cojure libs on http://clojars.org/
07:13jondot1nice, thanks, i guess maven is the de facto build system to use with clojure?
07:14raekjondot1: well, both yes and no. it is the de facto dependency system.
07:14raekand Leinginen uses those parts of Maven to do its job
07:14jondot1yep, ok.
07:14raekbut the de facto build system would be Leiningen
07:14raekthough some people use Maven too
07:16CmdrDats1jondot1: I use emacs and occasionally eclipse for browsing through java libs when I need to do java integration work
07:17raekjondot1: and for emacs integration, this is the only guide you should follow (the official one): https://github.com/technomancy/swank-clojure
07:17jondot1thanks
07:33b6nHi guys, whats the most pragmatic way to determine the index of an element in a sequence?
07:48llasramb6n: In Clojure that's honestly not a frequently-needed sort of idiom. Why do you need an index?
07:53b6nIIasram: I have an vector of keywords and if a keyword occurs at a lower index it has a higher 'value'. and I want to compare those values
07:55AimHereWell in that sort of case, perhaps a vector might not be the best data structure
07:57raekb6n: you can use the java api of vectors to do this: ##(.indexOf [:a :b :c] :b)
07:57lazybot⇒ 1
07:58raekbut to do a linear search might not be a very good solution
08:01b6nyes maybe picking a vector wasn't a good idea. I have a implementation using keep-indexed which works but feels not quite right :-)
08:03raekb6n: what do you want to do with these keywords and "values"?
08:05raekthe coice of data representation is often determined what kind of information you want to get out of the data
08:07raekbut if this isn't time-critical at all and is just a script you want to throw together the choice of data structures might not be that important
08:07b6nI want to implement a traditional card game in which the color of a card determines if it overtrumps another
08:07b6nthere are only 4 card colors
08:10raekwhere does the vector come into the picture?
08:11raekdo you have something like [:clubs :diamonds :hearts :spades] ?
08:11b6nyes exactly
08:11raekok now I understand!
08:11b6nso imagine :clubs overtrumps :diamonds and so forth
08:12b6n[:clubs > :diamonds > :hearts > :spades]
08:12raeksince the number of elements is very low and constant, .indexOf is very bad here
08:12raekanother way could be to use a map from suit to a number
08:12raekand constuct that map from the vector
08:13llasrams,very bad,not very bad, ?
08:13raekllasram: yes :-)
08:13llasramOnly because I was honestly confused for a sec :-)
08:13raek(def suit-order [:clubs :diamonds :hearts :spades])
08:13AimHereStill, if he's reinventing bridge, maybe he's doing it to learn to program, so it might be a good plan to teach him the right thing
08:14raek(def suit-value (into {} (map vector suit-order (range))))
08:15raekthen suit-value is {:clubs 0, :diamonds 1, :hearts 2, :spades 3}
08:15raekwhich also works as a function from suit to value
08:16raek(defn overtrumps? [suit-a suit-b] (< (suit-value suit-a) (suit-value suit-b)))
08:16raeksomething like this is how I would have done it
08:16b6nyes this looks much better than my (first (keep-indexed (fn ....
08:17raekthe biggest difference from the .indexOf approach is that the mapping from suit to value is only calculated once
08:19b6nI see, thanks a lot!
08:29llasramWhen is it necessary to explicitly reference a function by its var in order to for dynamic changes to that var to take effect?
08:34llasramI thought I had a handle on it, but I'm messing with Processing in Clojure, and am able to re-def functions and have the changes be picked up immediately in the running applet
08:34llasramIt kind of breaks my previous understanding of the compiler :-/
08:35raekllasram: whenever 'foo' is used in a function, it will be dereferenced. the cases you need to watch out for are when you keep the value of 'foo' for a long time
08:36raekfor example if you store it in a data structure or pass it as an argument to a function that runs for a long time
08:38raekso, a var #'foo is dereferenced whenever an expression foo is evaluated where foo is a free variable
08:38llasramI see. So that function won't be redefined, but anything it references via a var (via the normal implicit namespace resolution) will be
08:38raekyes, the function objects themselves are immutable
08:39AimHereHmmm. I'm dead new to this clojure stuff. Why does clojure give me integer overflows a lot sooner in slime/swank/emacs than it does when I run clojure from the command line?
08:40llasramI see. Ah! Yes, the situation I'd run into before where I needed to reference vars explicitly, I was generating reify'd objects by passing in function objects directly. Those functions objects were immutable, but their free refs are available for redef
08:40llasramThank you, raek :-)
08:40raekAimHere: is this for the same project?
08:40AimHereJust for a standard recursive factorial function
08:41raekAimHere: do you use the same version of clojure in the two setups?
08:42AimHereHeh, well I was using different ones and was so confused I dropped the .jar from one into the other to see what happens
08:42raekthe default behavior of auto-promotion of integers changed from Clojure 1.2 to 1.3
08:42AimHereStrangely, it doesn't seem to be recurring
08:42AimHereAh, yeah, I think that's the thing
08:43AimHereI think there may have been a 1.2 version kicking around at some point
08:44raekyou can either throw in a BigInt value in the computation (which will cause all partial results to be BigInts as well), or you can use the promoting ops: +', -', *', /', etc
08:44raek(factorial 100N) ;; BigInt literal as input
08:44raek(in Clojure 1.3)
08:45AimHereThanks. A lisp doesn't feel right if it doesn't spit out the factorial of 2000 in a jiffy
09:30mindbenderguys, how do you approach a problem space with a functional orientation?
09:40TimMcraek: Any idea whether using BigInts all the time is slower than checking every time whether promotion is needed?
09:41TimMcI feel like it would be, unless it is doing the checking itself... and even then, I *think* branch prediction (for BigInt-always) wouldn't be as advantageous.
09:43raekTimMc: no, I haven't studied how all this is implemented
09:44raekbut I would guess that a BigInt op is slower than a overflow check followed by a primitive op
09:47dnolenmindbender: that's a big question :)
09:47mindbenderdnolen: I agree
09:47dnolenmindbender: but generally I find there's less to think about
09:47dnolenmindbender: pick a data structure, write some functions
09:48mindbenderdnolen: some functions to interact with the data structure
09:49dnolenmindbender: yeah
09:50mindbenderdnolen: can such an approach be used to build a full blown solution?
09:50dnolenmindbender: yep
09:52mindbenderdnolen: I tend to put all code I look at within that frame. But most attimes the authors are not too kind to talk about why they chose such a structure and the need for the fuctions that accompany them
09:52TimMcraek: Sorry, I messed up my question... imagine an AutoPromoteInteger that kept a long and a BigInt under the surface.
09:53dnolenmindbender: well I find that it's usually obvious from the code
09:54dnolenmindbender: Clojure people tends to rely heavily only on maps, sets, vectors, lists. so few surprises
09:55mindbenderdnolen: what about the point for higher order functions, first class functions and macros, can they be put into any kind of simple perspective?
09:57dnolenmindbender: higher fns, first class fn already part of a simple perspective.
09:57jonasenIf I understand the ClojureScript One sample application correctly, there are two 'Views': form and greeting.
09:57jonasenIs there an easy way to add another view based on a new template?
09:58dnolenmindbender: macros take a while to understand but they solve a fairly common place problem.
09:58jonasenI'm probably missing something obvious
09:58jonasenI've created a template myview.html (based on greeting.html) and now I don't really know what to do next.
09:59mindbenderdnolen: can you try to put it into some perspective with regard to the structure we talked about i.e macros
09:59dnolenmindbender: simplest use case for macros is removing boilerplate.
10:00dnolenmindbender: but it scales up to writing compiler extensions without needing to actually change the compiler
10:02dnolenjonasen: looks like you need to add some code to view.cljs
10:03dnolenjonasen: then add a render method for that particular state
10:03jonasendnolen: I've added a new render method (defmethod render :myview ...)
10:03dnolenjonasen: but you also need to load it in the render :init method I think
10:05jonasendnolen: you mean in (fx/initialize-views ..)?
10:05dnolenjonasen: I think so
10:06dnolenjonasen: it looks like you need to change the one.sample.snippets/snippets macro as well
10:07jonasendnolen: Looking at the definition for initialize-views it seems to be hard-wired for form and greeting
10:07dnolenjonasen: it definitely is
10:07jonasendnolen: I'll take a look at snippets
10:18jonasendnolen: No luck yet, I'm new to "single page apps" so it's quite challenging.
10:19jonasenbut they seem to just move greeting out of view, so I guess I shoud do the same with myview
10:20dnolenjonasen: the way they manipulate views is not particularly generic or reusable.
10:20dnolenjonasen: remember one is just supposed to illustrate how a ClojureScript application might be constructed
10:20dnolenprobably makes sense to improve on the design
10:21jonasendnolen: Yes, maybe I should just edit the views that are already there for now. Until I understand the whole design better
10:49uberhanzAny pointers for someone wanting to learn clojure that knows (too) much java and loves haskell?
10:51Scriptoruberhanz: if you already know haskell you'll have a head start thinking of functional solutions for the exercises in http://www.4clojure.com/
10:52uberhanzthanks alot. looks like fun!
11:26phil__should i use clojure.contrib.trace or clojure.tools.trace?
11:26llasram~contrib
11:26clojurebotHuh?
11:26llasramDamn it
11:26dnolenphil__: you should not use anything from clojure.contrib
11:27phil__dnolen: is it outdated?
11:27dnolenphil__: yes
11:29phil__ok, any pointers on how i should set up https://github.com/clojure/tools.trace with lein? or should i just pull the source and stuff it into my project?
11:29phil__but this seems messy :/
11:30phil__or is there just a better way to trace function execution?
11:31llasramphil__: using `lein search' will search your configured repos for artifacts
11:32llasramsearching for tools.trace shows be that it's [org.clojure/tools.trace "0.7.1"]
11:32phil__ooh
11:33phil__i see, this is awesome
11:33phil__thanks a lot :)
11:34llasramNp :-) It does seem like something that you'd just want to slurp in to any random project, without needing to explicitly make it a dependency. Maybe a lein plugin?
11:39phil__llasram: why, is it bad to have extra dependencies on packages like tools.trace?
11:41llasramJust stuff you don't need. You can make it a dev-dependency, and then it isn't included in deployments etc, but it's still unnecessary if the committed code doesn't actually trace anything
11:43llasramThere doesn't seem to be a better way of referencing it ATM though, so a dev-dependency is probably the way to go
11:53devn&(= [1 4 9 16] '(1.0 4.0 9.0 16.0))
11:53lazybot⇒ false
11:55llasramOr more simply: ##(= 1.0 1)
11:55lazybot⇒ false
11:56dnolen##(== 1.0 1)
11:56lazybot⇒ true
12:41tufflaxHm, the docs say that = is supposed to compare numbers in a type-independent manner. ##(= 1.0 1) does not give that impression.
12:41lazybot⇒ false
12:41dnolentufflax: docs are out of date, == does that now
12:42tufflaxok :p
12:43AimHereWell (/ 1/6 (/ 1.0 6.0)) is still false, note!
12:44AimHere##(== 1/6 (/ 1.0 6.0))
12:44lazybot⇒ false
12:46LuytInteresting, there is a 'first' and 'second', but not a 'third' or 'fourth'. I guess you have to draw the line somewhere ;-)
12:46tufflaxAimHere that's expected, at least by me :p
12:46TimMcNot by me.
12:46tufflaxTimMc why not
12:46AimHere##(== 1/3 (/ 1.0 3.0))
12:46lazybot⇒ true
12:47tufflaxhm
12:47tufflax:p
12:47AimHereI guess it doesn't like rounding up
12:48LuytFloating point is only an approximation. And ##(type 1/3) is not the same as ##(type (/ 1.0 3.0))
12:48lazybot(type 1/3) ⇒ clojure.lang.Ratio
12:48lazybot(type (/ 1.0 3.0)) ⇒ java.lang.Double
12:49TimMcAimHere: Oh, what the...
12:49TimMcLuyt: So? ##(== 1 1.0)
12:49lazybot⇒ true
12:50LuytApparently 1.0 is a value that can be represented exactly in floating point.
12:50AimHereBut neither 1/3 nor 1/6 can be represented exactly
12:50LuytBut 1.0/3.0 is 0.3333333333333333 and where does the 333333333 end?
12:50AimHereWell unless you're taking a base with 3 (and/or 2) as the factor
12:51tufflaxSo why the difference in 1/6 and 1/3 results?
12:51tufflaxin the
12:51tufflaxas above :YP
12:51AimHereMaybe the internal representation of clojure doubles is in base 81
12:52LuytI think it's caused by the floating point implementation of the machine on which the code executes.
12:52LuytThe same problem crops up in any other program language which uses floating point.
12:53tufflaxMost (?) other languages don't have ratios though
12:53AimHereWell what other languages manage to compare double floats to inbuilt integer rational types?
12:53AimHereI mean, it's nice that it even works some of the time
12:54tufflaxHehe, I don't know about that :)
12:56TimMcI'd prefer consistency.
12:56TimMcI don't see any tickets on this; filing one.
12:56dnolenTimMc: ticket about what?
12:57AimHereThe == operator isn't overly consistent when comparing number types that were never meant to be compared in the first place !
12:58AimHereIt's a lucky day in most languages if your floating point type manages to equate 1/3 and 2/6
12:58TimMcdnolen: (== ratios floats) being inconsistent
12:58AimHereNever mind casting to rationals
12:59TimMcdnolen: (== 1/x (/ x.0)) false for x = 6, 7, 13, true for x = 2, 3, 4, 5, 8, 9, 10, 11, 12, 14
13:00TimMc$javadoc clojure.lang.Ratio
13:00lazybothttp://download.oracle.com/javase/6/docs/api/clojure/lang/Ratio.html
13:00TimMcbah
13:07AimHere##(#(if (= %2 0) 1 (*' %2 (%1 %1 (- %2 1)))) #(if (= %2 0) 1 (*' %2 (%1 %1 (- %2 1)))) 200)
13:07lazybot⇒ 788657867364790503552363213932185062295135977687173263294742533244359449963403342920304284011984623904177212138919638830257642790242637105061926624952829931113462857270763317237396988943922445621451664240254033291864131227428294853277524242407573903240321257405579568... https://refheap.com/paste/369
13:07AimHereOh sweet
13:09TimMcAimHere: Is that Ackerman?
13:09AimHereNah, just a Y combinator on 200!
13:10AimHere(#(%1 %1) #(%1 %1))
13:10AimHere##(#(%1 %1) #(%1 %1))
13:10lazybotjava.lang.StackOverflowError
13:10AimHereJust have to stresstest the bot ;)
13:10TimMc,(#(% %) #(% %))
13:10clojurebot#<RuntimeException java.lang.RuntimeException: java.lang.StackOverflowError>
13:16TimMcdnolen: Never mind, not filing a ticket.
13:16TimMcAimHere, tufflax: ##(double 1/6)
13:16lazybot⇒ 0.1666666666666667
13:16TimMc##(/ 6.0)
13:16lazybot⇒ 0.16666666666666666
13:17TimMcInverting the float munges it enough to make it inequal with the ratio.
13:17tufflaxwhy not? :p After thinking some more about it I think I have changed my view. I would expect ##(= 1/x (/ x.0)) to be true for all x, and that would, I think, be more useful. :P
13:18tufflaxEven if not totally true
13:18TimMc##(3.0 (/ (/ 3.0)))
13:18lazybotjava.lang.ClassCastException: java.lang.Double cannot be cast to clojure.lang.IFn
13:18TimMc##(== 3.0 (/ (/ 3.0)))
13:18lazybot⇒ true
13:19TimMc##(== 6.0 (/ (/ 6.0)))
13:19lazybot⇒ true
13:19TimMchuh
13:19tufflaxI mean, if you think of (/ x.0) as the double that results
13:21TimMc&(== 1/6 0.1666666666666667)
13:21lazybot⇒ true
13:22TimMcI'm just chalking this up to floating-point jitter and leaving it be.
13:32chewbrancaanyone have any recommendations for error handling with clutch and couchdb? right now the default is to throw an io exception with a string containing the http error code, but I would like to be able to react appropriately to different errors, specifically in this case, 409 conflict errors
13:44raekchewbranca: I would recommend slingshot in general for clojure programs. https://github.com/scgilardi/slingshot
13:46chewbrancaraek: nice, I've been meaning to look more into slingshot, time to dive in
13:54ziltiHow do I add a leiningen dependency which has a classifier? Where do I write the classifier?
13:54chewbrancaraek: cool, switched over to slingshot, looks like a nice approach to error handling. Won't help with dealing with string status messages, but overall using slingshot looks nice
13:57jkkramerzilti: [group/artifact "version" :classifier "foobar"]
13:57jkkramerzilti: per https://github.com/technomancy/leiningen/blob/master/sample.project.clj
13:57ziltioh, thanks!
14:06LuytHow do I do 'argument splatting' in Clojure? Like that (println 1 (splat [2 3]) 4) means the same as (println 1 2 3 4) ?
14:08brehaut,(apply println 1 (conj [2 3] 4))
14:08clojurebot1 2 3 4
14:10Luytis there no function that will unpack a collection so that the items can be passed individually instead of inside a collection?
14:10brehautLuyt: apply ^
14:10Luyt(conj [2 3]) doesn't expand into two arguments, 2 and 3.
14:10LuytOw moment, I'll look up apply
14:11brehautLuyt: build one seq, and use apply to pass it to the fn
14:11brehautno need for jiggery pokery voodoo
14:12LuytI was trying (disj a b) where both a and b are sets, but that didn't work as expected, but (disj a b1 b2 b3 ... bn) where bi are elements of set b
14:12Luytdid work.
14:12Raynes&(apply + [1 2 3])
14:12lazybot⇒ 6
14:13raekLuyt: have you seen clojure.set/difference?
14:13Luytraek: Yes, the tutorial mentiones that, but I was wondering whether there is a splat operator/function in Clojure.
14:14raekLuyt: you could use apply there: (apply disj a b) = (apply disj (cons a b)) = (disj a b1 b2 b3 .. bn)
14:14LuytHmmm, food for thought ;-) Thanks for all your tips, I'll figure something out ;-)
14:14raekthe variadic version of apply takes all elements between the first and the last and concats them to the last
14:15raekand then applies the function with those as the arguments
14:24uberhanzbest page when trying to learn clojure : http://clojure.org/cheatsheet
14:28LuytI'm currently working through http://java.ociweb.com/mark/clojure/article.html
14:30LuytI sometimes have to turn my brains inside-out ;-)
14:31uberhanzI usually like static (and strong) typed languages, but clojure is fun!
14:31LuytI was surprised that you can use a set or hashmap as a function to test for membership. Image the power that'd be unleashed if you could pass functions around!
14:32uberhanzhaha. new to functional programming?
14:32uberhanzor am I missing the irony?
14:33LuytI was a bit charging there ;-) I come from a C/C++/Python background. In Python, functions are first class citizens, like in Clojure. But I already passed around function pointers in C, so...
14:34brehautfunction pointers dont have any lexical context though
14:35AimHereI think his point is that he did the closest that he could to that sort of stuff in C
14:35LuytGood point. But when they don't use globals or have any side effects, that wouldn't be a limitation, would it?
14:36brehautits a huge limitation!
14:36LuytNo closures, indeed
14:36LuytNo fancy python decorator stuff
14:37brehautno super expressive combinators
14:37uberhanzthink about us poor ppl that have to use Java at work and have to keep their functional programming for home projects. weep for us!
14:37LuytAre you one of them?
14:37uberhanzyeah
14:38LuytThe problem is that corporations want to standardize on Java instead of just the JVM.
14:38LuytIn the latter case, you could use anything that produces java bytecode.
14:38uberhanzyeah
14:39LuytCorporations see "Java Programmers" as a commodity
14:39semperosusing clojurescript, working with a JavaScript library function that expects a JS object as a parameter
14:39uberhanzIts easier to start to write tools in other JVM based languages
14:39semperoswhat's the "right" way to go about this common task?
14:39TimMcLuyt: s/"Java Programmers"/people/
14:40semperosTimMc: s/people/walking-money-bags-with-no-life-outside-work/
14:40uberhanzhaha
14:43LuytI already suspected it'd be better to learn some Clojure instead of doing Java from 9 to 5 and couchpotato for the TV with a few beers at evening.
14:43AimHereCouchpotato with the TV and beer from 9 to 5, then learn some Clojure in the evening
14:44AimHereClearly the lifestyle of champions
14:44uberhanzWell, I actually not only do Java, but do email also! on the otherhand, I dont do couchpotato. not my thing
14:44wiseenis there a clojure parser library - something that would help parse macro grammars ?
14:45brehautwiseen: you mean something that deals with sexps?
14:45LuytI usually do Python during the day, but one has to keep on learning more powerful blob languages, no? http://paulgraham.com/pypar.html http://www.paulgraham.com/avg.html
14:46ziltiMy life's Clojure and Army, right now
14:46wiseenbrehaut, well something that will help me parse macro body, eg. I have a macro that can contain (message ...) (catch ...)* (close ...) (finally ...)
14:46wiseencatch can appear multiple times, others are optional
14:47wiseenparsing that from lists is tedious
14:47wiseenideally I could have some declarative way to specify the grammar ?
14:47RaynesI do exactly that in lazybot's plugin dsl. I use keywords for the names though, which make it clearer that you're not calling things by are supplying directives instead.
14:48Rayness/by/but/
14:49wiseenRaynes, link ?
14:50wiseenRaynes, do you do it manually or did you write a DSL for it ?
14:50RaynesManually.
14:51Rayneshttps://github.com/flatland/lazybot/blob/develop/src/lazybot/registry.clj#L121 Now, this is all probably pretty insane (this has been only marginally modified since originally created and was some of my first Clojure code), but the actual parsing stuff (I think) is fairly recently rewritten and isn't all that wild.
14:53phil___can somebody please tell me if this is considered bad form: https://gist.github.com/1653743, as opposed for example to this: https://gist.github.com/1653746
14:54phil___i prefer to use as few ifs and conds and cases as possible and let the language handle the test cases vie apply
14:54wiseenyeah the gorey internals of writing a parser manually, I'm suprised someone hasn't written a declarative parsing library - I'm guessing it would simplify writing macros a lot, and functional PLs usually have cool parsing libs (eg. FParsec F#)
14:55RaynesThe first example is much clearer, but I think that might because of the insane indentation in the second one.
14:55RaynesEr, reverse that.
14:55RaynesI clicked the links in the wrong order. :P
14:55RaynesYeah, closer inspection tells me that the second one is definitely the clearer of the two.
14:56phil___:D so the second is considered good practice? isnt it much clearer to have all edge cases layed out in front of you as in the first example?
14:58phil___it certainly looks much cleaner, but the explicit tests kind of conceal the intent i think
15:02phil___wiseen: just yesterday i read about a parsec like monadic parser in clojure: http://intensivesystems.s3-website-us-east-1.amazonaws.com/tutorials/monads_101.html?from=@
15:02phil___gotta scroll down a bit
15:03raekthere's also fn-parse: https://github.com/joshua-choi/fnparse
15:03tavis`Roman Gonzalez is about to release his port of attoparsec to clj
15:04tavis`it should be up on https://github.com/roman/ sometime soon
15:04tavis`zettaparse
15:08muhoohmm, kind of annoying (.split "foo bar baz" " ") doesn't give me a list of strings, it gives me a #<String[] [Ljava.lang.String;@10241ae>
15:08muhooinstead of ("foo" "bar" "baz") which i kind of expected
15:08Raynesmuhoo: That's a Java array of strings. It is seqable, so you can treat it essentially as what you want.
15:09Raynes&(seq (.split "foo bar baz" " "))
15:09lazybot⇒ ("foo" "bar" "baz")
15:09Raynes&(map #(str % " hi") (.split "foo bar baz" " "))
15:09lazybot⇒ ("foo hi" "bar hi" "baz hi")
15:10raek,(clojure.string/split "foo bar baz" #" ")
15:10tavis`&(clojure.string/split "foo bar baz" #" ")
15:10lazybot⇒ ["foo" "bar" "baz"]
15:10clojurebot#<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.lang.ClassNotFoundException: clojure.string>
15:10RaynesI wish people wouldn't use that as an opportunity to avoid explaining the difference between Java arrays and Clojure seqs and how you can use them in Clojure.
15:11muhoouberhanz: could be worse, you could be force to use PHP at work
15:11muhooRaynes: thanks!
15:11Raynesraek: Not that you are guilty of such acts.
15:12RaynesI occasionally see people with muhoo's query get shown an example of clojure.string/split and told "See! This does it!" and a fantastic opportunity for them to learn about Java collections is missed.
15:12RaynesIt's tragic, really.
15:13muhooi am very thrilled to be able to use seq to turn some nonsense #<BS[] [Ljava.lang.BS into a nice lispy list
15:14raekexactly :-)
15:14Raynesmuhoo: Keep in mind that, unless you're trying to print the array, you don't usually have to call seq on it.
15:14muhooit's just repl sugar for me, but it makes me happy :-)
15:15Raynesmuhoo: Most of Clojure's functions do that implicitly. Like my map example.
15:15Raynes:)
15:18muhoohousekeeping question, the bot is & or ##?
15:18muhoo&"foo"
15:18lazybot⇒ "foo"
15:18muhoo##"foo"
15:18muhoohmm
15:18brehautboth of those are lazybot
15:18raekblahblah ##"foo"
15:18brehautclojurebot is prefixed with a comma
15:18muhoo,"foo"
15:18clojurebot"foo"
15:18raekblahblah ##(identity "foo")
15:18lazybot⇒ "foo"
15:18muhoowait, there are two bots?
15:19brehaut,(inc 1)
15:19clojurebot2
15:19brehaut&(inc 1)
15:19lazybot⇒ 2
15:19brehauttheres also hsbot
15:19muhoo!
15:19tavis`hsbot?
15:19cold_gopherHi all. I have just installed SWANK and I am launching it from emacs. When I'm in the REPL and perform a doc such as (doc map), I get an exception. Anyone come across this before?
15:20brehauthaskell bot i think
15:20tavis`what's it doing here? ;)
15:20brehautcold_gopher: the swank repl is different to the normal repl
15:20brehautcold_gopher: you need to use clojure.repl if you want the normal tools. however, slime provides alternatives through emacs that you can use
15:21cold_gopherok thanks
15:21brehautcold_gopher: C-c C-d C-d for docs
15:21brehaut(on a var)
15:21brehautworks in the repl and editor
15:21cold_gophernice
15:24wjlroebrehaut: oh man, I didn't know that and was looking for that yesterday - thanks!
15:24wjlroeCould not find it in the C-h b listing for some reason
15:26brehauti cant find the one for looking up the source of a var
15:27tavis`eldoc is also quit handy with slime: https://gist.github.com/1551858
15:29wjlroeAlso useful - break points in swank - http://hugoduncan.org/post/2010/swank_clojure_gets_a_break_with_the_local_environment.xhtml
15:29Raynesbrehaut: lazybot evals Haskell too.
15:29Raynes&he 3 + 3
15:29lazybotjava.lang.RuntimeException: Unable to resolve symbol: he in this context
15:29RaynesDuh.
15:29Raynes$he 3 + 3
15:29lazybot⇒ 6
15:29brehautRaynes: thats good, becuase i cant remember the hsbot commands :P
15:30Licenserheh
15:30tavis`$he take 6 (cycle [1,2,3])
15:30Raynesmuhoo: ##(println "is for evaluation of code embedded inside of a message (when you can't begin the message with &)")
15:30lazybot⇒ is for evaluation of code embedded inside of a message (when you can't begin the message with &) nil
15:30lazybot⇒ [1,2,3,1,2,3]
15:30raekthis is interesting: http://skife.org/java/unix/2011/06/20/really_executable_jars.html
15:32brehaut$he let fib = 1 : 1 : zipWith (+) fib (tail fib) in take 10 fib
15:32lazybot⇒ [1,1,2,3,5,8,13,21,34,55]
15:32Raynes$ht "you can even check types!"
15:32lazybot⇒ Type: "you can even check types!" :: [Char]
15:32Licenserwow that is the most terse definition of fib I've ever seen o.O
15:32RaynesI wonder why i prefix that with 'type'.
15:32RaynesLicenser: Welcome to Haskell. May I take your coat?
15:33LicenserRaynes that is astonishing
15:33brehautLicenser: its the canonical 'i have lazy values!' version
15:33Licenserso I have a real hard time to understand it
15:33Licenserso you should be able to do about the same in clojure shouldn't you?
15:33brehautyou can…
15:34brehautyou probably need to use a delay or a promise to tie the knot though
15:34brehautor use a def, which is a potential space leak ;)
15:34Licenserso let … in … is like (let [..] …) right?
15:34brehautcorrect
15:35Licenserso the definition of fib is 1 for 1 or zipWith (+) fib tail fib for all others?
15:35brehaut(concat [1 1] (map + …))
15:35tavis`what would lazybot do with an infinite list?
15:35Raynes: is cons
15:35Raynestavis`: Try it out.
15:35Licenserah
15:35brehautor (list* 1 1 (map + … i guesss
15:35Licenser$(range)
15:36tavis`$ht [1..]
15:36lazybot⇒ Type: [1..] :: (Num t, Enum t) => [t]
15:36Licenser,(range)
15:36clojurebot(0 1 2 3 4 ...)
15:36Licenserclojurebot is a sneaky bastard &&
15:36Licenser&(range)
15:36lazybotjava.lang.OutOfMemoryError: Java heap space
15:36Licenserlazybot will post the infinit list to github? :P
15:37RaynesHaha, well, normally he would stop after so many seconds and print an error message saying he timed out.
15:37Licenserbut this is too fast ^^
15:37RaynesIn this case, he has reached the memory limitations I've set for him.
15:37RaynesNo, that would usually be fine.
15:37LicenserRaynes can't you test for lazy lists and make it print it like clojurebot ?
15:37RaynesLicenser: I'm pretty sure he just sets *print-length*, and yes, I could do that too.
15:38Licenserprint-length is cheating
15:38RaynesI agree.
15:38Licenseryou could build your own pr-str to be smrt
15:38Raynes&(range)
15:38lazybotjava.lang.OutOfMemoryError: Java heap space
15:38RaynesHuh. I guess I've got the timeout set too high.
15:38Licenseror create a clojure version that has infinit memory space
15:38Licenserand internet bandwith
15:39Licenserwell range will fill your memory quite quick I guess
15:39RaynesYeah, but that didn't always blow the heap. Don't think we tried that since we changed the memory settings.
15:39RaynesAnyways, ##(+ 3 3)
15:39lazybot⇒ 6
15:39RaynesHe's still okay.
15:40tavis`and he can't be tricked to flood the channel?
15:40RaynesWith code? No.
15:40muhoo&(range 20)
15:40lazybot⇒ (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)
15:40Raynes&(range 500)
15:40lazybot⇒ (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 ... https://refheap.com/paste/371
15:40tavis`nice
15:40muhooooh, nice
15:40brehaut&(let [fib (promise)] (deliver fib (concat [1 1] (map + @fib (rest @fib))))) (take 10 @fib))
15:40RaynesYou can, of course, spam him with eval requests which would make him flood, but you'd be flooding the channel too and it wouldn't be much of a trick.
15:41lazybotExecution Timed Out!
15:41brehautrats
15:41Raynes^ is what it is supposed to do rather than blow the heap.
15:41brehauti have clearly forgotten how to use the promise trick
15:41Raynesbrehaut: Promise you've forgotten.
15:41Licenser&(println "bla")
15:41lazybot⇒ bla nil
15:42Licenser&(println "bla\nblubb")
15:42lazybot⇒ bla blubb nil
15:42Licenseraww he strips line breaks :P
15:42Licenser&(println "bla\nrblubb")
15:42lazybot⇒ bla rblubb nil
15:42Licenser&(println "bla\nrblubb")
15:42lazybot⇒ bla rblubb nil
15:42Licenser&(println "bla\rblubb")
15:42lazybot⇒ blablubb nil
15:42Licenser:(
15:42raek%(println "foo\u0000bar")
15:42raek&(println "foo\u0000bar")
15:42lazybot⇒ foo
15:42Raynes,(println "foo\nbar\nbaz")
15:42clojurebotfoo
15:43clojurebotbar
15:43clojurebotbaz
15:43muhoowhat is this, bot torture?
15:43Raynesmuhoo: This is spam that you've instigated.
15:43tavis`,(print "&(print 1234)")
15:43clojurebot&(print 1234)
15:43lazybot⇒ 1234nil
15:43RaynesNow feel guilty about it.
15:43muhooRaynes: i do indeed.
15:43brehaut,(print "(dec Raynes)")
15:44clojurebot(dec Raynes)
15:44lazybot⇒ 12
15:44Raynesclojurebot is not my biggest fan.
15:44tavis`so lazybot is a bit smarter than clojurebot about preventing the other bots from listening
15:44Licenser,(println "&(println \"&(+ 1 1)\")")
15:44clojurebot&(println "&(+ 1 1)")
15:44lazybot⇒ &(+ 1 1) nil
15:45Licenser,(println "&(println \"##(+ 1 1)\")")
15:45Licensernow that didn't work
15:45lazybot⇒ 2
15:45clojurebot&(println "##(+ 1 1)")
15:45lazybot⇒ 2
15:45Licenseroh it did
15:45muhooa bot as a macro expander
15:45Licensernow I wonder if you make them ping pong
15:45Licenserso to say a quine :P
15:45RaynesNo, you can't.
15:45LicenserRaynes are you sure?
15:45Somelauw&(def fib (lazy-cat [0 1] (map + fib (rest fib))))
15:45Bronsa,(let [fib (promise)] (deliver fib (lazy-cat [1 1] (map + @fib (rest @fib)))) (take 10 @fib))
15:45clojurebot(1 1 2 3 5 ...)
15:45lazybotjava.lang.SecurityException: You tripped the alarm! def is bad!
15:45tavis`,(print ",(print 1234)")
15:45clojurebot,(print 1234)
15:45RaynesYes.
15:45Licenseroh I guess lazybot ignores himsef?
15:46Rayneslazybot has to ignore himself -- the IRC server doesn't send you your own messages.
15:46RaynesBut that isn't the problem.
15:46Licenserut?
15:46Licenserbut?
15:46Rayneslazybot can't invoke clojurebot because he prefixes eval results with an arrow.
15:46Licenserbut lazybot can invoke lazybot ##(str "##(+ 1 1))
15:46lazybot⇒ 2
15:47Licenserbut lazybot can invoke lazybot ##(str "##(+ 1 1)")
15:47lazybot⇒ 2
15:47Licenserhmm seems it can't
15:47Licenserbut lazybot can invoke lazybot ##(str "#" "#(+ 1 1)")
15:47lazybot⇒ "##(+ 1 1)"
15:47RaynesIt can't because that is a limitation of the IRC protocol.
15:47Licenserah yeas he does not see himself
15:47Licenserhah
15:47Licensersneaky we have to con clojurebot into having something like ## ^^
15:47Licenserthen we can make them do a bot war
15:47ordnungswidrigLicenser: don't feed the bots! :-)
15:48Licenser^^
15:48Licenserbut it would be fun
15:48muhoo"fun" in the sense that setting old xmas trees on fire is fun
15:48Licensermuhoo yes
15:48muhoonot very productive though.
15:49Licenserproductive is for once overrated and then it is relative
15:49Licenserbreaking clojurebot in the beginning was quite productive ^^
15:49SomelauwSeems like promise makes a variable and deliver sets that variable
15:49Licenserif it hand't been done there would never have been the whole jailing thing
15:49Raynesclojurebot is still pretty easy to break.
15:49RaynesThe jail at least.
15:50RaynesBut I'm not sure he is going for safe with that one.
15:50LicenserRaynes just because it is not using clojail or clj-sandbox :P
15:50SomelauwSo, that's how you make non-global recursive lists. I asked before but nobody knew.
15:50RaynesWell, lazybot's clojure plugin has essentially been a battleground for testing clojail.
15:51tavis`have you played with running clojurescript in jailed env?
15:51Raynestavis`: Sure, we call that 'your browser'.
15:51Raynes;)
15:52tavis`bot style I mean
15:52RaynesNo. I'd be tempted to refheap the compiled javascript and tell you to run it your damn self. :p
15:52tavis`hehe
15:53tavis`'your browser' isn't really a safe jail though
15:53RaynesIt's safe for me though.
15:53tavis`very true
15:55ordnungswidriganyboy else having problems with slime-edit-definition? When invoking on a function defined in a protocol I get NPE in File/init called by slime-find-file
15:56tavis`yeah, it doesn't work yet
15:56tavis`I'm working on that
15:56ordnungswidrignice.
15:57tavis`if you move your point to the protocol itself you'll get pretty close to it
15:57ordnungswidrigI wonder if we can have jump it to the function implementation, not the protocol definition.
15:57tavis`metapoint works on protos but not proto funcs
15:58technomancy_nice to have someone helping with slime who actually cares about protocols
15:58tavis`I saw you prefer multimeths
15:59SomelauwWould it be possible to write a letrec macro in clojure using the promise/deliver primitives?
16:00technomancy_tavis`: a better way to say it would be that I don't work on any problems myself for which the speed of protocols is valuable enough to outweigh the inconveniences =)
16:05SomelauwHow to STOP clojure in emacs
16:05Somelauwbefore my stack explodes?
16:06SomelauwI need to stop it quickly?
16:06tavis`slime-interrupt might
16:06ordnungswidrigSomelauw: kill the java process.
16:06Somelauwalt+x not working
16:07SomelauwSomething like ctrl-c?
16:07tavis`then kill -9 java
16:07SomelauwOkay, I killed everything.
16:09SomelauwThanks. Can't slime be stopped by ctrl-c or something?
16:09RaynesIt can be stopped by force killing your Emacs.
16:09Raynes;)
16:09technomancy_tavis`: I think it would be perfectly acceptable to skip byte compilation of the .el payload files are remote
16:09SomelauwThat's what I did. I force killed emacs
16:10technomancy_as long as they get loaded; the byte compilation is nice for everyday speed, but it's an optimization. using jack-in remotely seems like not an everyday task.
16:10muhoois there a way to deref something where all i have is the text printout of the reference, i.e. #<Server Server@160bf50> ?
16:10technomancy_tavis`: of course if you intend to use it as part of normal development then maybe not; depends on your plans for it
16:10muhoois there any way to turn that text into the object that it sort-of-describes?
16:13ordnungswidrigtavis`: is hte npe fixed in swank clojure head?
16:14ordnungswidrigtavis`: do worry. It is. just found it.
16:18raekmuhoo: not in general. you can use the *1, *2, and *3 variables though if you evaled it recently
16:36Bronsahttps://github.com/clojure/clojure/blob/master/src/clj/clojure/repl.clj#L124
16:36Bronsashouldnt it be a set?
16:37arkhhow do I tell what version of clojure I'm running at a repl? I'm not sure if my emacs setup is using my project clojure of 1.3 or the 1.2 it installed with "lein plugin install swank-clojure 1.3.4"
16:37Bronsaoh, i see, i misunderstood
16:37Bronsa,(clojure-version)
16:37clojurebot"1.3.0"
16:38arkhBronsa: thank you
16:39dnolen,*clojure-version*
16:39clojurebot{:major 1, :minor 3, :incremental 0, :qualifier nil}
16:43tavis`technomancy_: we could also just copy the remote files to local and then byte-compile locally
16:44tavis`any thoughts on a security warning first?
16:52ziltiIs it a bug or a feature that things like (. (new Foo) (bar x)) aren't possible?
16:52nodenameHi, I have an app built as a Counterclockwise project. I've been asked "Where's the project.clj?" How can I make my project runnable outside Eclipse?
16:53ibdknoxzilti: huh? that is possible
16:54ibdknox,(. (Integer. "2") (toString))
16:54raek&(. (new Object) (toString))
16:54lazybot⇒ "java.lang.Object@1139c27"
16:54clojurebot"2"
16:54ziltiibdknox: I have the problem that it isn't possible - but it's possible if I first store it in a variable and then do a (. foo (bar x))
16:56ibdknoxthat seems unlikely
16:56ibdknoxwhat's the exception?
16:56ibdknoxand the exact code
16:59ziltiIt's a simple NullPointerException
16:59ordnungswidrignodename: you can package it as a jar
16:59ibdknoxordnungswidrig: I think he's asking how to take a CCW project and make a project.clj from it so it'll work in lein
17:00nodenameordnungswidrig: yes, what ibdknox said
17:00ordnungswidrigI see.
17:00ziltiI've already changed the code... Actually I used the .. macro. I had to change the whole thing because the .. macro seems to have problems with mutable java classes anyway. But I wanted to ask if that's a known problem
17:04dnolenzilti: there's no problem. many mutating methods return void instead of a value.
17:11ishkabiblwow this is a big irc channel
17:12ishkabiblis Raynes here?
17:12RaynesYep.
17:13ishkabiblI saw your "try coljure" interactive web appliction(at first I didn't realize you made it)
17:17Raynesishkabibl: Yup, that'd be me.
17:18ishkabiblhows your book comming?
17:18RaynesAt least partially. I didn't do much of the design portion.
17:18RaynesSlowly but surely.
17:18ishkabiblwell it has your name on it(try clojure)
17:20Raynesishkabibl: I wrote the majority (all?) of the backend and the initial design. Other people came along and streamlined it, because I wasn't fantastic at web design.
17:20ishkabiblI see
17:21ishkabiblare maps persistent?
17:22RaynesYep.
17:22ordnungswidrigishkabibl: everthing it but refs, atom and agent.
17:22Raynes&(type {:foo 0})
17:22lazybot⇒ clojure.lang.PersistentArrayMap
17:22ordnungswidrigishkabibl: and java classes
17:22Rayneshttp://clojure.org/data_structures
17:24phil___is it possible to simplify the following code in some way? https://gist.github.com/1654274
17:26ishkabiblmaps must use vectors to store their buckets
17:27dnolenishkabibl: object arrays more likely
17:28ishkabiblare object arrays just java arrays?
17:28ordnungswidrigphil___: (if (symbol? a) [a (cons a b)] [a b]) can be simplified to [a (if (symbol? a) (const a b) b))]
17:29ordnungswidrigphil___: i.e. you can inline the if into the vector creation
17:30ishkabiblwait, there are 2; sorted and hashed. the sorted one makes sense(it's just a tree like haskell's map) but the hashed one makes less sense
17:30tauntaunDoes Clojure have a standard library for the basic combinators (S, K, etc.)?
17:30phil___ordnungswidrig: oh yes, thx :)
17:31ishkabibl tauntaun: if not you can use fn for lambda clalcules to implment it
17:33tauntaunishkabibl: I'm quite aware of that :) I prefer not to reimplement even small simple things.
17:33ishkabiblya, me too :)
17:39tavis`tauntaun: http://www.thelastcitadel.com/blag/combinator
17:40technomancy_tavis`: that would work too; depends on how much effort you want to put into it. either approach is valid.
17:43chewbrancawhat do you guys use for web request loggin? more specifically with noir?
17:47tauntaunWow, I must be communicating really poorly :)
17:47tavis`same, that was my way of saying I can't find one
17:50tavis`tauntaun: there's various parser combinator libs, but I can't see anything packaged up for S K I,etc.
17:52ordnungswidrigchewbranca: ngnix or apache in front of it
17:54chewbrancaordnungswidrig: I'm looking for something in the app itself
17:54chewbrancaI found an example logging ring middleware that looks like it will get me going: http://techbehindtech.com/2011/01/19/introduction-to-clojure-web-development-using-ring-compojure-and-sandbar/
17:55ordnungswidrigchewbranca: never thought of it but writing a ring middleware to log looks trivial
17:55chewbrancayeah much simpler than I expected
17:55ordnungswidrigchewbranca: that's clojure!
17:56chewbrancaordnungswidrig: ?
17:56ishkabibli belive he is saying that clojure makes everything easy
17:56ordnungswidrigchewbranca: clojure makes it easy :-)
17:56ordnungswidrigthe rest is written here: http://en.wikipedia.org/wiki/Common_Log_Format
17:57chewbrancaoh lol, yeah I agree, been astonished with how powerful and concise clojure is
17:57chewbrancaI'm honestly less interested in using the commong log format as I would much rather use actual machine readable logs, either as raw clojure data structures or json
17:58chewbrancabut that depends on whether you're more interested in processing logs with shell utils or something higher level
18:00chewbrancanice, and logging is working
18:54clj_newbwhy is (type (doall (map identity '(1 2 3)))) a lazy seq? doens't doall force exection of the list?
18:56clj_newbhiredman , amalloy_ : ping ^
19:01clj_newbwhy is (type (doall (map identity '(1 2 3)))) a lazy seq? doens't doall force exection of the list?
19:02tmciver,(doc doall)
19:02clojurebot"([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."
19:02XorlevClojure always surprises me. I cringe thinking how hard something will be, then end up being (usually) pleasantly surprised.
19:02clj_newbtmciver: so it executes the entire list ... and then why is it still lazy?
19:03tmciverclj_newb: That's a great question and I'm not positive about the answer but it looks like doall walks the sequence then returns the head so the type is whatever was passed to doall.
19:04clj_newbtmciver: (source doall) agrees with you. I'm now baffled on how clojure handles laziness.
19:06tmciverclj_newb: the return type of map is a lazy sequence; this fact does not change just because the sequence has been realized.
19:06tmciverit's a realized sequence of type LazySeq
19:07clj_newbI think I get it now
19:07clj_newbdorun can be run _multiple_ times
19:07clj_newbso the side effects can happen multiple times
19:07clj_newbI had thought dorun ran it _once_ if it was lazy + then cached the results
19:08clj_newbinstead, dorun will happily do the sid effects multiple times
19:09tmciver,(doc dorun)
19:09clojurebot"([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."
19:09clj_newbsorry, s/dorun/doall
19:09tmciveryeah, it looks like dorun is like doall except it does not retain the head of the sequence.
19:09tmciverAh
19:09clj_newbtmciver: anyway, this is clear to me now; thanks for helping me debug my understanding
19:10tmcivernp, it helped me too.
19:10clj_newbthe example I was getting at is that (doall (doall (doall blah))) would do the side effects of blah 3 times
19:10clj_newbwhereas in my mental model, the first doall would execute it; cache the results, and the latter 2 do alls would do nothing
19:10clj_newbclearly I was wrong
19:11clj_newbwait
19:11tmciverYes, looks like the sequence is realized and kept in memory but side effects are reproduced.
19:11clj_newb,(doall (doall (doall (map (fn [x] (println x)) '(1 2 3)))))
19:11clojurebot1
19:11clojurebot2
19:11clojurebot3
19:11clojurebot(nil nil nil)
19:11clj_newbit's only executed once, not 3 times
19:12brehautclj_newb: doall just realizes the seq. once its realised, the thunks are not called again
19:12TimMcclj_newb: A lazy seq caches the results of the computations.
19:12clj_newbbrehaut: I'm baffled. Why is the return value of a doall a lazy sequence then?
19:12brehautclj_newb: because thats its type.
19:13clj_newbis my brain weird; or do others also find this counterintutivie?
19:13brehautclj_newb: a lazy seq is either an empty seq, or a head, and another lazy sequence that will be computed by need
19:13clj_newbif the list is executed + caught; why is it lazy rather than a normal list?
19:13tmciverclj_newb: the println is called in map's function; that function is not called when doall executes.
19:13brehautclj_newb: lazy sequences are a flow control construct, not a data structure
19:14TimMcclj_newb: When I do (let [t (range)] (take 20 t)), that forces range to produce the first 20 elements, but the rest are not produced. The result is still a seq, but the head is realized and the tail is not.
19:14brehautclj_newb: what programming languages did you use prior to clojure?
19:14clj_newbbrehaut: scheme + clojure
19:14clj_newberr, scheme + haskell
19:15brehautclj_newb: im baffled. this is exactly the same as it is in haskell, and im pretty sure scheme has an equivalent
19:15clj_newbbrehaut: scheme, iirc, isn't lazy, though chapter 3 of sicp implements lazy cons
19:15TimMc$seen zmaril
19:15lazybotzmaril was last seen quitting 1 week and 2 days ago.
19:15brehautclj_newb: scheme has laziness via delays and there are lazy streams available
19:16brehautclj_newb: clojure isnt lazy either
19:16TimMcnot as a language
19:16TimMc(that was ambiguous -- I was agreeing with brehaut)
19:16tmciver? Clojure not lazy? Now I'm confused.
19:16clj_newbhere, can we walk through this example (doall (doall (map (fn [x] (println x)) '(1)))) ? I thin this is the simplest test case that demonstrates m confusion
19:17brehauttmciver: clojure is a strict language with some lazy datastructures (notably lazy seqs and delays)
19:17TimMctmciver: Haskell is inherently lazy. Clojure is eager, but has a tricky construct for laziness.
19:17brehauttechnically haskell is not lazy either, its non-strict ;)
19:17TimMchmm
19:17tmciverBut many functions return lazy seqs, e.g. map, yes?
19:17brehauttmciver: yes
19:19tmciverSo for a language to be considered lazy, all of it's data structures should exhibit laziness?
19:19clj_newb,(do (def b (map (fn [x] println x)) '(1 2 3))) (doall b) (doall b))
19:19clojurebot#<Exception java.lang.Exception: SANBOX DENIED>
19:19TimMcclj_newb: You'll want to use let there.
19:19tmciverNo def for you!
19:19TimMcbeing a shared environment
19:19clj_newb,(let [b (map (fn [x] (println x)) '(1 2 3))] (doall b) (doall b))
19:19clojurebot1
19:19clojurebot2
19:19clojurebot3
19:20clojurebot(nil nil nil)
19:20clj_newbwhy is it only printed once?
19:20clj_newbI had two (doall b)'s
19:20brehauttmciver: its to do with the calling convention as much as it is by the datastructures. haskell can have strict datastructures too
19:20clj_newbwhy are the thunks only executed once?
19:20clj_newband if the results are cached, then why is the list still lazy?
19:20SomelauwBecause map remembers the results.
19:20tmciverclj_newb: the fn is called when map executes - not when the doall's do.
19:20brehautclj_newb: because once a lazy seq cons cell has been realized, attempting to realize it again is a no-op
19:20SomelauwUse doseq instead of map if the side effects matter
19:21clj_newbtmciver: map is lazy; it doens't execute it until the doall
19:21clj_newb,(let [b (map (fn [x] (println x)) '(1 2 3))] (println "after map") (doall b) (doall b))
19:21tmciverAh, yes, you're right.
19:21clojurebotafter map
19:21clojurebot1
19:21clojurebot2
19:21clojurebot3
19:21clojurebot(nil nil nil)
19:21clj_newbbrehaut: so the results are cached in a _lazy_ list?
19:21brehautclj_newb: yes
19:22clj_newbI find this counterintutiive, but I accept it.
19:22brehautclj_newb: why would it be counter intuitive?
19:22clj_newbbecause I feel the return type of a doall should be a normal list
19:22clj_newbit's no longer lazy, i have executed all the p[arts of it, and I have the results
19:23clj_newbin my mind, (doall x) = (apply list x)
19:23brehautclj_newb: whats the difference between a realized lazy sequence and a 'normal list'?
19:23clj_newbbut clealry that is NOT the case
19:24tmciverbrehaut: the type!
19:24SomelauwI am not sure if the realized lazy sequence might need less memory
19:24clj_newb, (println (str (doall (map identity '(1 2 3))))) (println (str (apply list (map identity '(1 2 3)))))
19:24clojurebotclojure.lang.LazySeq@7861
19:24clj_newb(println (str (apply list (map identity '(1 2 3)))))
19:24clj_newb,(println (str (apply list (map identity '(1 2 3)))))
19:24clojurebot(1 2 3)
19:24clj_newb,(println (str (doall (map identity '(1 2 3)))))
19:24clojurebotclojure.lang.LazySeq@7861
19:24clj_newbthat is the difference
19:24clj_newb(I'm doing file serialization, and lazyseqs are screwing me up)
19:25brehautclj_newb: clojure is heavily oriented toward interfaces over concrete types.
19:25TimMcclj_newb: Here it is: A seq is either a generator or a cons cell. A cons cell is a pair of a realized value ("first") and a seq ("next"). When you ask for the first of a generator seq, it is converted into a cons cell with the computed value, and a "next" of a new generator. Ignore the name "LazySeq" here, it is an implementation detail.
19:26brehautclj_newb (and tmciver): so saying 'the type of X is T' is non-idiomatic
19:27brehautif i recall correctly the biggest difference between list and lazy seq is that list is counted and seqs are not
19:27brehaut(map counted? [(list 1 2 3) (map identity 1 2 3)])
19:27brehaut,(map counted? [(list 1 2 3) (map identity [1 2 3])])
19:27clojurebot(true false)
19:27Somelauwvector is counted, i don't know about list, but it probably isn't
19:28brehautSomelauw: ^
19:28tmciverbrehaut: 'type of X is T' may be non-idiomatic but it's still true.
19:29TimMcbut not always useful
19:29brehauttmciver: of course its still true
19:29tmciverI would say it's useful in learning the inner workings of Clojure.
19:30brehauttmciver: sure
19:31tmciverThanks to clj_newb, brehaut and TimMc: I learned something! :)
19:33clj_newbI'm soem awesome people learn things from answering my qeustions.
19:33clj_newbI should charge people tuition to teach me.
19:35clj_newb,(read "({})")
19:35clojurebot#<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to java.io.PushbackReader>
19:35clj_newbwhy can't I read that as an list of a empty hash?
19:35brehaut,(read-string "({})")
19:35clojurebot({})
19:35TimMcHmph, where did Somelauw go? I wanted to show them the diagram on http://www.brainonfire.net/files/seqs-and-colls/main.html
19:35clj_newbbrehaut: thanks!
19:36brehautclj_newb: be aware that the reader evals by default
19:36TimMcsee *read-eval*
19:37brehaut,(read-string "#=(inc 1)")
19:37clojurebot#<RuntimeException java.lang.RuntimeException: EvalReader not allowed when *read-eval* is false.>
19:37brehautah of course the bot has it the other way round
19:37TimMceven clojurebot has it disabled
19:37tmcivermeaning they don't eval by default?
19:38TimMctmciver: at all
19:38TimMcThe default is true, they have it set to false.
19:38brehaut,(eval ":noluck!")
19:38clojurebot#<Exception java.lang.Exception: SANBOX DENIED>
19:38clj_newbhang on: (1) read-eval does NOT evalute the sexp it returns (2) read-eval will evaluate _special_ reader-eval forms #=. Are both statements correct?
19:38brehautclj_newb: correct
19:39tmciverbrehaut: kindly tell me what the #= is.
19:39brehautclj_newb: you need #=… reader macro expressions to get read eval
19:39TimMc,(let [evil (resolve (symbol "eval"))] (evil `(+ 2 2))) ; brehaut
19:39clojurebot4
19:39brehaut&(read-string "#=(inc 1)")
19:39lazybotjava.lang.RuntimeException: EvalReader not allowed when *read-eval* is false.
19:39brehautTimMc: haha its much easier in clojurebot than lazybot apparently :)
19:39TimMcRight, lazybot is actually locked down pretty well.
19:40tmciverTimMc: that gets by clojurebot because it's looking for the symbol eval?
19:40TimMcA bit overly so at the moment. ##(binding [*out* 4] *out*)
19:40lazybotjava.lang.SecurityException: You tripped the alarm! pop-thread-bindings is bad!
19:40tmciverand not the string?
19:40TimMctmciver: Yeah, clojurebot is a dunce.
19:40clj_newbjust so we are clear; suppose my sworn enemy sends me a read-this.clj , I should read it with *read-eval* set to false?
19:40TimMcclj_newb: Right.
19:40tmciverShh, he might hear you!
19:41TimMcclojurebot: Are you offended?
19:41clojurebotHuh?
19:41TimMcSee, no problem.
19:41tmciverwow, he IS a dunce! :)
19:41tmciverOr he's hard of hearing.
19:41clj_newbclojurebot: Have you been so offended you can't think clearly?
19:41clojurebotPardon?
19:42TimMcMight just be deaf.
19:42brehautxml rpc api's seem to be universally poorly specced out
19:42TimMclazybot, would you stand for such treatment??
19:42lazybotTimMc: Uh, no. Why would you even ask?
19:45clj_newbwe should give the bot ops
19:45clj_newbthen whenver anyone asks it a question or uses it
19:45clj_newbwith a certain probability they get kicked
19:45clj_newbit'd be hilarious
19:45TimMcWe should have someone with ops at all. -.-
19:46TimMcalthough I've only ever seen 3 people in here that needed kicking.
19:46clj_newbor ... suppose you tell cojurebot to evaluate something; and it throws an exceptino ==> kicked; it times out ==> silenced; etc ...
19:47jayunit100SCIP is wayyyyy too long has someone abridged the good parts
19:47TimMcI think stack overflow -> kick was proposed at one point.
19:47tmciverwhy was the #= reader macro needed in the examples above?
19:47TimMctmciver: For demonstration.
19:47tmciver,(read-string "#=(inc 1)")
19:48clojurebot#<RuntimeException java.lang.RuntimeException: EvalReader not allowed when *read-eval* is false.>
19:48clj_newbjayunit100: when I read a book that I feel is too basic; I read the hardest chapters first
19:48tmciver,(read-string "(inc 1)")
19:48clojurebot(inc 1)
19:48lazybot⇒ 5
19:48clj_newbthen I read the others as necesary to understand the hard chapters
19:48TimMctmciver: Clojure uses it internally for some stuff.
19:48TimMctmciver: Try it in your repl.
19:49TimMctmciver: ##(binding [*print-dup* true] (pr-str {:a 3}))
19:49lazybotjava.lang.SecurityException: You tripped the alarm! pop-thread-bindings is bad!
19:49TimMcbah
19:49TimMc,(binding [*print-dup* true] (pr-str {:a 3}))
19:49clojurebot"#=(clojure.lang.PersistentArrayMap/create {:a 3})"
19:49jayunit100wait how do you "run" the "inc 1" closure that is returned
19:49tmciverTimMc: hmm, *read-eval* is true but (read-string "(inc 1)") returns (inc 1)
19:49tmciverTimMc: I expected it to eval it.
19:50TimMcYou're misunderstanding #=
19:50jayunit100oh duh eval
19:50tmciveryes
19:50TimMc#= says "read this next form, eval it, and substitute that as the form"
19:50tmciverI'm not even sure what it does, I don't believe it's documented.
19:50TimMcIt's not really documented, and that's a security problem. I've opened a ticket for it.
19:51tmciverTimMc: OK, but I thought read-string eval'd too.
19:51TimMcyep
19:52TimMcOh, only with #= forms
19:52tmciverAhh.
19:52tmciverSo read-string returns an un-eval'd form, but prefixed with #= it gets eval'd
19:53tmciver(if *read-eval* is true)
19:55TimMchttp://dev.clojure.org/jira/browse/CLJ-904 <-- there's the ticket, feel free to vote for it!
19:56TimMcRight, so (first (read-string "[a b #=(+ 1 3)]")) => 'a
19:56TimMcThere's no "unbound symbol a" problem, because eval is restricted to that one little thing.
19:57TimMc#= has some limitations, too. (read-string "#=(type (+ 1 2))") => clojure.lang.PersistentList -- only the top layer is "unquoted"
19:58tmciverTimMc: I think I got it but what do you mean by "eval is restricted to that on little thing"?
19:59tmciver,(first [a b c])
19:59clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(NO_SOURCE_PATH:0)>
20:00jayunit100best way to learn clojure is to code w/ a broken parenthesis key.
20:00jayunit100forces you to read the docs before typing stuff.
20:01TimMctmciver: What would you expect (type (+ 1 2)) to produce if it were eval'd?
20:02tmciverTimMc: without looking . . . Integer?
20:02TimMcLong, in 1.3, but yeah.
20:02tmciverRight
20:02brehautim not sure if type is a sensible function these days. havent we moved away from :type metadata?
20:02TimMcSo why didn't read-string produce java.lang.Long?
20:02tmciverTimMc: I'm just wondering why you mentioned the unbound symbol problem.
20:03TimMcbrehaut: Right, I should use class there.
20:03tmciverTimMc: ttyl, supper time!
20:03TimMctmciver: Because of something you said earlier -- I think you've removed that misconception by now. :-)
20:15TimMcThe default bindings for starting and stopping a macro recording in Emacs are C-x ( and C-x )? That's *so cute*!
20:16brehauthaha :)
20:18tavis`so why does #= need to exist in the first place?
20:32seancorfieldslime/swank startup problem: Unable to resolve symbol: pst-elem-str in this context, compiling:(swank/core.clj:128) -- what's the likely cause?
20:32seancorfieldi saw this mentioned the other day here and have forgotten the cause/solution sorry :(
20:33tavis`it's a clj-stacktrace version issue
20:33seancorfieldyup, not sure where to look to track it down
20:33tavis`if you're using swank-clojure as a plugin rm clj-stacktrace from your lib/
20:34seancorfieldi did have it installed as a global plugin and just deleted that but it's still giving me the error
20:34tavis`put it back as a plugin and get rid of your project's clj-stacktrace jar
20:35tavis`swank-clojure unfortunately depends on a newer version of clj-stacktrace than what a lot of libs pull in
20:36seancorfieldah, looks like it's the lein-cljsbuild plugin... time to switch from global to dev-dependency!
20:36tavis`ah, I hit that yesterday as well
20:37tavis`:exclusions in ~/.lein/init.clj might work
20:38tavis`btw, do you have any idea why running the sample projects in lein-cljsbuild pops up a java window?
20:39seancorfieldhaven't tried that... i've just been using lein cljbuild auto
20:40TimMctavis`: Lookat my message @ 19:52 (20:42 here now)
20:42actsasgeekhello clojurians. I'm trying to do something I think should be easy but apparently not. I want to have the user (me) input a string "plane flies-to paris" and have it evaluated as (plane flies-to paris game-state). plane is a function as is flies-to. paris resolves to a keyword. game-state is a parameter to method that's doing this.
20:43actsasgeekI've tried all kinds of crazy combinations of eval and apply and I just can't quite get it to work.
20:44TimMcactsasgeek: Make a lookup map like {'plane plane}.
20:44TimMcYou really don't want to be using eval for this...
20:45brehaut,(let [[fname & args] (.split "plane flies-to paris" " ")] [fname args])
20:45clojurebot["plane" ("flies-to" "paris")]
20:45tavis`TimMc: yeah, I saw that. I get what it does, but I'm curious what problems it was invented to solve.
20:46TimMctavis`: Exactly that -- preserving types. (records were involved, I think...)
20:46tavis`oh, I think I get it now
20:46actsasgeekbrehaut: I tried something similar. let me give that version a go.
20:46TimMcactsasgeek: Oh, symbol and resolve might be what you're after, but I still recommend the explicit lookup table.
20:47actsasgeekTimMc: it seems to be the arguments that cause the difficulty.
20:47brehautactsasgeek: TimMc's explicit table look up is smart
20:47TimMcbrehaut: I just used that for a CLI application. :-)
20:48brehaut,(let [table {:plane (fn [action target] (prn "the plane" action target))} [fname & args] (.split "plane flies-to paris" " +")] (apply (table (keyword fname)) args))
20:48clojurebot"the plane" "flies-to" "paris"
20:48actsasgeekyeah, I've done that in Python.
20:48TimMcactsasgeek: Have you gotten to the point where you have the name resolved to a function?
20:48brehautTimMc: necessary-evil does similar for xml rpc ;)
20:48actsasgeekfor that particular attempt, I was mapping symbol over the splitted string.
20:49actsasgeekhttps://gist.github.com/1655048 is the latest...I just need to figure out the right thing to do to args.
20:50TimMcactsasgeek: Symbols need to be resolved before they can be used.
20:50actsasgeekso (resolve (symbol function))?
20:52brehautcorrect
20:52TimMc,(let [c (map (comp resolve symbol) (.split "comp - inc" " "))] c)
20:52clojurebot(#'clojure.core/comp #'clojure.core/- #'clojure.core/inc)
20:53TimMc,((let [c (map (comp resolve symbol) (.split "comp - inc" " "))] (apply (first c) (rest c))) 8)
20:53clojurebot-9
20:54TimMcTrying to simplify that apply...
20:56brehautTimMc: if you make the split string " +" then it splits on 1 or more spaces
20:56brehaut,((juxt #(seq (.split % " ")) #(seq (.split % " +"))) "a b")
20:56clojurebot[("a" "" "" "b") ("a" "b")]
21:00TimMc&(filter seq (.split " a b c " " +")) ;; leading and trailing too
21:00lazybot⇒ ("a" "b" "c")
21:00TimMcalthough that's not the only way
21:00actsasgeekthe annoying thing is that if I insert the literal for what I want, it works. but I can't seem to get the "args" part to work correctly. more specifically, the "game-state" symbol doesn't want to resolve correctly because it is a closure over a method parameter.
21:01seancorfieldtavis`: thanx for you help - i have swank back up and running and i still have lein cljsbuild auto running on my other project! :)
21:01TimMcactsasgeek: Is game-state a local?
21:01actsasgeekTimMc: yes.
21:02TimMcThen you're screwed (for this approach) -- Clojure does not have reified environments.
21:02actsasgeekah.
21:02TimMceval, resolve, etc. -- none of those can see locals
21:02seancorfieldnow of course my question is how to get swank up and running on a project that has lein-cljsbuild as a dev dependency :)
21:02seancorfieldyou mentioned something about exclusions
21:02actsasgeekI guess I'll have to give up on a purely functional approach then.
21:03TimMcactsasgeek: eval and resolve aren't really staples of a functional approach anyhow
21:04actsasgeekTimMc: yeah, but I need some sort of interface.
21:04TimMcLookup tables are a fine approach.
21:04actsasgeekbut I still can't send the arguments to it.
21:05TimMcYou'd have to explain the larger picture -- why does the user need to know the internal names of your functions?
21:05actsasgeekI think the lookup tables is fine but those functions will need to modify global game state in the simulation since it can't be passed around.
21:05TimMcYou can special-case 'game-state
21:05actsasgeekwell, they don't...there is a vocabulary for controlling the game.
21:07jessetrimblenew to clojure - having some trouble wrapping my head around java regex and newlines
21:07TimMcAnd that's what the lookup maps are for -- connecting game vocabulary to internal var names.
21:07actsasgeekwhat really happens is that "plane flies-to paris" calls a (plane flies-to paris game-state) and plane calls the method (flies-to paris plane-game-state) so the subject determines what game state gets changed.
21:08jessetrimble(re-matches #"(foo)" "foo") will match foo
21:08actsasgeekright but I was trying to avoid any global variables.
21:08TimMcactsasgeek: You don't need any, that's what I'm telling you.
21:08jessetrimblebut (re-matches #"(foo)" "foo\n") doesn
21:09jessetrimble1. is this the right place to be asking these types of questions, and 2. if so, anyone have any suggestions?
21:09TimMcjessetrimble: ##(re-matches #"foo" "foox") it's not about newlines
21:09lazybot⇒ nil
21:09actsasgeekTimMc: but you can do other things with plane...you can do "plane refuels"
21:09actsasgeekI don't want to have to look up every possible string combination.
21:09seancorfieldnm, i add :exclusions [clj-stacktrace] to the lein-cljsbuild dev-dependencies entry and everything is working fine now - yay!
21:10actsasgeekunless I'm missing something obvious. I'm used to doing things like { "name" : function}[ "name"]( args) in Python.
21:11jessetrimbleTimMc: I see. Coming from regular expressions in the Ruby world…I see I have some research to do. Thanks
21:12TimMcjessetrimble: re-matches is a whole-string match
21:12seancorfieldi spoke too soon... i obviously don't have the syntax right on the exclusion
21:13TimMcjessetrimble: look at re-seq and re-find as well: (find-doc #"^re-")
21:13jessetrimbleawesome, will do. thanks for pointing me in the right direction
21:14TimMcNB: re-seq behaves differently w/ and w/o groups
21:24tavis`seancorfield: put it at the top level of the project def
21:24tavis`(defproject ... :exclusions [clj-stacktrace])
21:24tavis`at least that's what worked for me
21:24seancorfieldtavis`: oh, i didn't even know it could go there? i realized i had a regular dependency that also pulled it because of ring or something...
21:24seancorfieldlet me try that
21:25tavis`I'm tem
21:25tavis`pted to fix swank-clojure to work with older versions of it
21:28clj_newbA = (java.awt.Color. 0.8 0.8 0.8) ; B = ((fn [x] (java.awt.Color. x x x)) 0.8) . A works fine. B throws an exception. Why?
21:29clj_newb,(java.awt.Color. 0.8 0.8 0.8)
21:29clojurebot#<Color java.awt.Color[r=204,g=204,b=204]>
21:29clj_newb,((fn [x] (java.awt.Color. x x x)) 0.8)
21:29clojurebot#<IllegalArgumentException java.lang.IllegalArgumentException: No matching ctor found for class java.awt.Color>
21:30TimMcHmm, maybe a promotion issue.
21:30TimMcDoes it take floats?
21:31TimMcclj_newb: ##(#(java.awt.Color. % % %) (float 0.8))
21:31lazybot⇒ #<Color java.awt.Color[r=204,g=204,b=204]>
21:32augustlhow do I get query parameters on pages in noir?
21:32augustldoing a /search?q=foo type thing
21:32clj_newbTimMc: brilliant debuggin. Thanks!
21:33seancorfieldtavis`: thanx man - perfect!
21:37actsasgeekTimMc: thanks for your help. I got a lookup table version to work...so far. slainte.
21:39seancorfieldanyone know if lein-cljsbuild pulls in enough dependencies to start a clojurescript repl?
21:40seancorfieldcljs.repl.rhino doesn't seem to have everything it needs... some org.mozilla.context stuff is missing... not a biggie but it would be nice to get it running
21:41augustlis it just me, or is noir very unfunctional? https://github.com/ibdknox/noir/blob/master/src/noir/request.clj for example
21:41augustlglobal state? :S
21:42TimMcclj_newb: I remember the last time I used Color, it was annoying to call 'float on all the args.
21:42tavis`seancorfield: I think it does
21:42seancorfieldaugustl: it's a pragmatic choice to make the web semantics easier to work with
21:43seancorfieldi took a functional approach in fw/1 but it makes session and cookie stuff a bit stranger to work with
21:43seancorfieldtavis`: hmm, i guess i'm just trying the wrong thing to get a cljs repl running then
21:44tavis`it won't work in swank
21:44tavis`see this http://p.hagelb.org/lein-cljs-swank.html
21:44TimMcaugustl: It's not as bad as unchecked mutable globals -- that's a dynamically scoped var.
21:44tavis`phil's trick to start a cljs repl alongside swank
21:44augustlTimMc: I see, I guess noir is more clever than I am :) Especially since I'm new to clojure.
21:45seancorfieldtavis`: thanx - i'm in your debt tonight
21:45seancorfieldsigning off for dinner... back later maybe :)
21:46tavis`also out of here, that's enough geeking for a day
21:46TimMcaugustl: That (binding ...) just introduces a thread-local value for *request*, it doesn't affect global state.
21:47augustlTimMc: ah I see
21:59augustlwhat's the best way to create a method that has one optional argument?
21:59augustlfunction, sorry :)
21:59augustlI have a function that returns vectors for a search form, and it may or may not have a prefilled value
22:01augustldoh, I can just pass nil when calling the function
22:05TimMcaugustl: Sometimes you'll see (fn foo ([x] (foo x default)) ([x opt] ...))
22:08TimMcThere's also the ugly trick ##((fn [x & [opt]] (list x opt)) 4), but that doesn't even let you specify a non-nil default.
22:08lazybot⇒ (4 nil)
22:39apwalkaugustl: This might be what you're after - https://gist.github.com/1655342
22:48alexbaranoskywhat do you all think of using (defn ^:private foo ...) instead of (defn- foo ...) ? I'm starting to feel partial to the consistency of using ^:private everywhere instead of having a special case for defn- (as well as thinking the '-' is not a very readable way to distinguish the two visually)
22:54leo2007how does flightcaster.com predict flight delays?
22:55TimMcalexbaranosky: Sounds good to me.
22:56Raynesalexbaranosky: I'm in favor because defn- shouldn't exist in the first place.
22:57alexbaranoskyare you guys doing this in your projects?
23:01TimMcI probably should.
23:01TimMcI still don't know how I feel about private vars in the first place.
23:01alexbaranoskywhat are your concerns?
23:01alexbaranoskydo you think they should be letfns ... or do you just think everything should be public?
23:03alexbaranoskyI tend to avoid private vars, but use letfns... the var in question is tested (in another file) so it can't become a letfn without me changing tests around, which I don't feel is worth the time
23:04TimMcWhat's your use-case for private vars?
23:04alexbaranoskycan still be tested
23:04TimMcNo, I mean hiding stuff in the first place.
23:05TimMcOCD, implicit non-API, cleaner use-alls...
23:05alexbaranoskyin my opinion too many public functions make understanding the intended usage of a ns harder
23:06TimMcThat's where a well-documented public API comes in handy... -.-
23:06alexbaranoskyif the private stuff builds up to be too much, then it might graduate to its own NS
23:06TimMcI really don't like this "docs are optional" mentality the community seems to have.
23:07alexbaranoskyI guess I come from a school of thought that code should be as readable as possible first, then the documentation is icing on the cake
23:07alexbaranoskydocs are not optional for users, I agree
23:08TimMcMeh.
23:08alexbaranoskyI more mean for developer readability
23:08technomancy_TimMc: a public var implies a promise to not change it until a major version bump
23:08technomancy_that's ... huge.
23:08alexbaranoskythat too :)
23:08TimMctechnomancy_: You see a public var as implicitly part of the API?
23:08alexbaranoskyI absolutely do
23:08TimMcThat makes sense from my Java background, I guess.
23:09technomancy_TimMc: in the absence of explicit documentation stating "the public API consists only of the vars in the foo.bar" namespace, absolutely
23:09technomancy_I've started using ^:internal metadata to signify stuff that's not part of the public API but still subject to change if I can't make it private for whatever reason
23:10alexbaranoskytechnomancy_, what is a reason you might not be able to make something private?
23:10TimMc:private seems... *complected* :-P
23:10alexbaranoskywith what?
23:11technomancy_alexbaranosky: plenty of places where just because another namespace needs access to it doesn't mean I'm ready to commit to the function sticking around.
23:11alexbaranoskynot using seems to me, to complect that which is meant for user consumption and that which is implementation detail
23:12TimMcalexbaranosky: It is used to determine both refers and the default API
23:12alexbaranoskytechnomancy_, yup. I'd usually put that function in a shared internal ns, but I think I tend to use more NSs than most
23:12technomancy_:private complects the act of communicating to the consumer and whether a var will show up in ns-publics
23:12TimMcbut mostly I just wanted to use that word.
23:12philis it faster to just reverse a list or to (concat list element) instead of (cons element list)?
23:12TimMctechnomancy_: You're not willing to use the #' hack?
23:12alexbaranoskybut not using private also has issues... hence adding the idea of ^:internal
23:13technomancy_TimMc: I'll use it for tests, but not for implementation
23:13alexbaranoskymost languages have more than just private and publics, so internal seems to make sense
23:14TimMctechnomancy_: Do you intend ^:internal to be machine-readable?
23:14llasramRanting: what needs to be done to fix things such that the Clojure website tells you to use Leiningen?
23:14technomancy_TimMc: no
23:14technomancy_TimMc: I guess it would be cool if marg and friends honored it though
23:14TimMcsure
23:15llasramWas out with friends tonight. Brought up Clojure. One had tried to try it, but installed "clojure" package from homebrew (I believe?), got a REPL with no readline support, got no help from clojure.org, and gave up in disgust
23:16technomancy_llasram: some of the folks in Core have no idea how lein works. one of them told me they don't use it because they don't want all their libraries to have AOT applied to them.
23:16technomancy_(which was how it worked back in 1.0.0; late 2009)
23:17dnolenllasram: someone should try to get clojure removed from homebrew, apt-get, etc
23:17technomancy_it has to be in apt-get because it's a dependency of lein and debian won't ship uberjars
23:17alex_baranoskyllasram, more complaining / more helping make it happen?
23:17technomancy_but the shell script wrapper should probably be removed from the apt-get package
23:18TimMcphil: You want to reverse a list, or you want to add something to the end?
23:18TimMcIf the latter, you might want to use vectors instead.
23:18Raynesalex_baranosky: No, because I hadn't thought of it before. I assure you that I will from now on.
23:19alex_baranoskyRaynes: I've got my fingers poised for a global search and replace of Midje over here :)
23:19Raynesalex_baranosky: Do my projects afterwards for a cookie.
23:19alex_baranoskywhat kind?
23:19alex_baranoskyMolasses and I'll do it
23:20dnolenalex_baranosky: just to throw in my vote, I'm against defn- and :private as well
23:20llasramalex_baranosky: But where? Telling people that clojure.org is useless and they should be looking at some random (to them) github project is hard
23:20alex_baranoskydnolen, so no letfns either?
23:20dnolenalex_baranosky: I like letfn
23:21TimMcdnolen: What are your reasons for hiding fns?
23:21dnolenTimMc: not hiding, clarity, readability
23:21alex_baranoskyok, then I agree. tend to use letfn for all new stuff
23:21llasramtechnomancy_: Yeah, down with the shell script wrapper. I need to try the Debian package again... Last time I gave it a whirl, ant compat issues made it explode, but I assume that was transitory (or at least totally solvable)
23:22llasramdnolen: How?
23:22dnolenllasram: how?
23:22TimMcllasram: I think replaca handles clojure.org -- but you'd have to get Clojure/core as a whole to agree to make lein an official tool, if they haven't already.
23:22alex_baranoskyllasram, have you brought it up on the mailing list? If I had enough excitement for that particular cause that is where I would start
23:22TimMcalex_baranosky, dnolen: Doesn't letfn make testing hard?
23:23llasramdnolen: Sorry. How to get the package removed from homebrew? I mean, I have no connection to the Mac community. I assume it was created by a Clojure enthusiast?
23:23TimMcOr are you more focused on integration-style testing?
23:23alex_baranoskyI tend to only write tests of public things. Just like I would in an OO language
23:23dnolenTimMc: depends, but I'm not a big tester. I test high level functionality, no patience for testing small fns.
23:23alex_baranoskybut like other most things, it depends
23:23TimMcThere's something to be said for that -- tests are often treated as API demos.
23:24llasramalex_baranosky: That's probably a constructive way to start
23:24TimMcalex_baranosky: You tend to do top-down testing anyway, right?
23:24alex_baranoskyTimMc, that's not a bad thought
23:24llasramTimMc: Useful info (re: replaca). Mostly just ranting now, but I'll look back at the log tomorrow morning and contemplate
23:25llasramAnyway, </rant>
23:25TimMcI know s/he does the autodocs.
23:25alex_baranoskythere are a lot of things I thinkshould be letfns but instead private vars in Midje that aren't because of how they are tested
23:25philTimMc: im adding elements to a list in a recursive function but need to reverse it at the end, or alternatively (concat e2 e1) instead of (cons e1 e2) at every step
23:25philand im wondering which is faster
23:26philis concat of 2 lists O(1)? it should be i guess
23:27dnolenphil: concat is linear in the first list, but it's lazy.
23:27dnolenfirst seq I should say
23:28TimMcphil: You could build a vector and give back an (rseq ...) on it, if the consumer only needs a seq.
23:30philbut consing to a vector must be must slower than consing to a list right?
23:30TimMcphil: conjing, actually. It's complicated, since vectors are 32-way trees under the surface
23:32philyea i read about the implementation somewhere - basically when just conjing data is copied once every 32 conjs right?
23:32philelse just add to the current 32 element vector
23:33TimMcphil: You might also look at transients.
23:33TimMcUltimately... it comes down to profiling. :-/
23:33philunfortunately it needs to be compatible to clojurescript
23:34philyea i guess :/ so concat is linear but lazy?
23:34TimMcSame algorithm running in both languages?
23:34philyea
23:34TimMcYou should know that CLJS doesn't really have persistents yet.
23:35philexactly :)
23:35dnolenphil: clojurescript doesn't have efficient persistent data structures
23:35phildnolen: i know, i looked at the implementation, right now vectors are just copied on right if i understand correctly
23:35philbut porting the java version to javascript should be relatively easy
23:36dnolenphil: yup. if efficiency is a concern you've always got arrays and loop/recur
23:36philim planning on doing it somewhen
23:38phildnolen: i understand... im not really writing very performance sensitive code right now, just trying to understand the "best practices" since im new to clojure
23:38philbasically, when to use what data structure, what are the implications etc etc
23:39dnolenphil: best practice - don't worry about it. stick to the abstractions.
23:39TimMcVectors are usually the right answer for random access.
23:39dnolenphil: CLJS doesn't have any data structures that you can update quickly, except for lists.
23:39philso just (cons) to list and then (reverse)?
23:40dnolenphil: if reverse is the important bit, conj on to vector then reverse
23:40TimMcphil: If you cons to list, it will be the same as conjing onto a vector.
23:41philyea but still, right now conjing to a vector is basically linear in cljs
23:41TimMc&(cons 1 (cons 2 (cons 3 ())))
23:41lazybot⇒ (1 2 3)
23:42TimMcphil: Sure, but that will change by the time you have to care.
23:42philwhich is then gonna turn into O(n^2) when conjing at every step
23:42philTimMc: are the data structures gonna be ported soon?
23:42TimMcNo idea.
23:43TimMcDevelopment seems to have ramped up, though.
23:43dnolenphil: keep something in mind, mutability aint so bad if you don't let it escape.
23:43philok, thats good, but it shouldnt be that hard i guess
23:43phildnolen: but there are no transients in cljs anyway right?
23:44dnolenif you don't need to constantly add to something you can construct a mutable array but return something that only supports a functional interface
23:44philhow is a mutable array constructed?
23:45dnolenphil: I doubt they will be ported anytime soon, I don't think the JS engines generally have the kind of perf you need
23:45phili mean in cljs
23:45dnolenmaybe V8 is getting close
23:45dnolen(array)
23:45phildnolen: but copy on write must be must slower than a ported PersistentVector??
23:45lazybotphil: Definitely not.
23:46TimMcOh, lazybot...
23:46RaynesHahaha
23:47philand tbh i dont think theyre that slow in js tbh
23:47dnolenphil: not for small data structures. Clojure data structures rely on some hard core things - fast bit twiddling, machine representation of JVM arrays etc
23:47phili took the java version and put it through gwt
23:47phil100k conjs in 2secs on safari on an old macbook
23:47dnolenthat's crazy slow.
23:48philwell it depends on what you wanna do
23:48phili mean yea, if you wanna do machine learning in the browser its slow
23:48dnolenphil: sure, but you could also 100k push onto an array and return a functional thing and save yourself the trouble.
23:49philif you want to do some ui with clean immutable data structures its more than enough
23:49dnolenphil: definitely, but what's there now is good enough for that as well.
23:50phildnolen: also true :) but cant see any disatvantage in porting them to js
23:51phili mean the only thing i saw thats kinda harder in js is counting bits in an integer
23:51philand there are some black magic O(1) algorithms for that without having to rely on a cpu instruction
23:51alex_baranoskyhmmm it looks like defn ignores its attr-map? parameter
23:52dnolenphil: it would be fantastic for someone to try to port them and do some benchmarks
23:52TimMcphil: like log2
23:52dnolenphil: as you say for large amounts of data they pay their way
23:52TimMcalex_baranosky: Depends on the form you use, i think.
23:52dnolenbut storing 100,000 in a client side JS app seems like a waste of memory.
23:52alex_baranoskylooking at the source, and I don't see the param used
23:53alex_baranoskyoh durrrrr
23:53TimMcalex_baranosky: Which attr-map? There are 3...
23:53phildnolen: yea, i cant imagine what youd need 100k elements for client side
23:54philbut 10k i can imagine
23:54alex_baranoskyTimMc, I see now
23:55philand copying 10k elements every time you update that vector cant be good
23:55alex_baranoskyTimMc, so what is wrong with this?: (defn as-validation-error ^:private [form] ...)
23:56TimMcalex_baranosky: You've put the meta on the args.
23:57TimMc^:private foo gives you a symbol foo with metadata, and the defn macro should pick that up. An explicit arglist is different.
23:57dnolenphil: anyways, not saying it wouldn't be interesting to pursue!
23:58dnolenphil: some one should do it and report back with benchmarks in various browsers, Node.js etc.
23:58dnolenphil: also might be interesting if TypedArrays offer any perf advantage
23:58alex_baranoskyTimMc: this fails too: (defn ^:private as-validation-error [form] ...)