#clojure logs

2014-04-20

00:51kenrestivodoes this already exist in something else, some other library? https://www.refheap.com/77773
01:13oinksoftIn C i might have enum LogLevel { DEBUG, INFO, WARNING, ... } and then i can do DEBUG + 1 to get INFO, etc. How would you do this in Clojure?
01:13oinksoftwhere you have some constant values that can refer to each other
01:16beamsowhy wouldn't you just use INFO instead of DEBUG + 1?
01:16kenrestivooinksoft: pretty sure there are c-like enums in java. you could always do a java class if you want that behavior, and access it from clojure
01:17beamsoi haven't seen anyone do that sort of enum math in java
01:18kenrestivootherwise you could hack something like (def loglevels {:debug 1, :info 2, :warning 3}), and (set-loglevel (inc (:debug loglevels))
01:22kenrestivoi've done it in java before as public enum SomeEnum {FOO, BAR, BAZ}; and then i guess you could do SomeEnum.FOO + 1, but not sure the use case
01:31hiredmanin clojure enum type things are typically not numbers, but keywords, so no math
02:07oinksofthiredman: hm ok
02:07oinksofthiredman: well the math part (comparison) can be useful: http://www.bpaste.net/show/Jh105vI7FoTM77sl5iAN/
02:07oinksofthiredman: pardon the poorly written macro? this is my first one so i don't know the idioms 100%
02:07oinksoftkenrestivo: hm ok, this is the sort of use case i was thinking of (that paste)
02:08TEttingeroinksoft: ##(let [log-level [:debug :info :warning] inverse-log-level (apply hash-map (interleave log-level (range))) access-log (fn ([log-key] (get inverse-log-level log-key :not-found)) ([log-key modifier] (get log-level (+ (inverse-log-level log-key) modifier) :not-found)))] (access-log :debug 1))
02:08lazybot⇒ :info
02:08TEttingeroinksoft: ##(let [log-level [:debug :info :warning] inverse-log-level (apply hash-map (interleave log-level (range))) access-log (fn ([log-key] (get inverse-log-level log-key :not-found)) ([log-key modifier] (get log-level (+ (inverse-log-level log-key) modifier) :not-found)))] (access-log :debug 99))
02:08lazybot⇒ :not-found
02:09TEttingersome fun tricks there, interleave is a useful function for generating hashmaps
02:09oinksoftTEttinger: i see that there are many fun tricks in there...
02:10TEttingerheh, it would be clearer split up
02:10oinksoft;)
02:10TEttingerbut it fits in one IRC message so there
02:10oinksoftbut you can compare levels w/ that?
02:10TEttingeryes
02:11oinksoftwhat does that look like?
02:11TEttingeraccess-log with one arg, like :debug , produces an int or :not-found
02:11TEttingerstarting at 0, going to the max index in the vector log-level
02:11TEttingerI am absolutely certain this can be done better by a more experienced clojurer
02:12TEttingerin particular I bet macros could help, but I haven't touched them
02:12TEttinger(there's probably some way I'm not seeing yet)
02:13oinksofti see, you have just constructed a reverse lookup
02:14oinksoftthanks TEttinger, that's nice and simple
02:14oinksoftalthough i do like my enum macro ;)
02:17gunsFTR, it's nice to have things like (def FATAL 0) as actual source code
02:18oinksoftyou speak for the record?
02:19gunsthis chat room is logged, so yes :)
02:19oinksoft:)
02:19oinksofti guess the nice thing in C is you get the type too
02:19oinksoftwhen you use an enum
02:20gunswell, you can ^:const simple Clojure values
02:20gunsand you can use core.typed or schema for the typing
02:20oinksoftand you could wrap thatall up in an enum macro ;)
02:20guns(or a simple ^long I suppose)
02:20oinksofti'll look at core.typed and schema
02:20gunshaha yes. Although I had my fill of that kind of thing in ruby
02:21gunscancer of the semicolon, as they say
02:21oinksofthehe
02:22oinksoftwell i am on that side of things but now i am working a job in clojure and i see that the clojure community often seems to favor extremely high level abstraction
02:22oinksoftworking in ruby for years i had the same conclusion as you
02:23oinksoftbut i feel some pressure to add lots of syntax to clojure programs? do you notice this guns ?
02:23oinksoft*syntactical sugar
02:23gunsI think the idea behind the community's love for abstraction is building things around protocols, etc
02:23gunsso, no
02:23gunsI think it's actually the opposite!
02:23oinksoftmaybe this is just the tone of instructional books
02:23oinksofti am reading two from manning press
02:23oinksoftit reminded me of the ruby community, was turning me off tbh
02:24gunsThere are differing opinions, but those of us who suffered through Rails projects favor being explicit
02:25gunsI don't really see projects deffing a set of vars in this fashion for instance; it's fine for source code to be tabular
02:25PlatzI thought the protocol stuff was for perf gains in the jvm toon
02:25oinksoftfor me it is not an implicit/explicit thing ... it is reading rails code and one big method has been split into 80 tiny ones that only are there for that one thing in the first place. too much indirection?
02:25gunsPlatz: that too; but it gives you 80% of what you want from polymorphic code
02:25oinksoftbut yes, indirection = soul of computer science or something
02:26gunsoinksoft: lol; I stepped through a rails app once and found myself ~16 super calls deep
02:26gunsmaybe it was worse
02:26oinksoftbetter to forget :)
02:27gunsI'd say the Clojure catchphrase is "it's all data"
02:27Platzdare i say tiny polymorphic assemblages lead to category theory
02:28gunshow is that? Clojure's protocols don't feel like a "kind-of" relationship
02:29gunsnot allowing inheritance helps alot
02:30arrdemguns: just because it's not supported doesn't mean people don't use it..
02:30arrdemguns: and we do have hierarchies which are entirely inheritance based..
02:31gunsarrdem: that's true; I'm just saying extending protocols isn't a feature
02:31gunsusing the existing Java class hierarchy is quite nice because it's nicely designed
02:33arrdemeh... it depends. I guess I agree in spirit that protocols aren't an inheritance based extension mechanism but I'd also argue that I've personally gotten a good bit of millage out of my own additional implementations of my own and others protocols.
02:33arrdemso they're still very much a client driven extension mechanism
02:33arrdemabet in a much more static manner than say multimethods
02:35gunsI'm open minded. It's just nice that writing Clojure code isn't usually a practice of "extend these magic base classes and mixin this magic module"
02:36arrdemoh totally
02:37arrdemit's much more a "oh here's this map datastructure, do what you will with it and here's how to get/make more"
02:37oinksoftwould it be weird to do (def some-fn (let [stuff (atom {})] (fn ...))) ? or is this common?
02:37arrdemand I think that the focus on the data rather than the structure of the manipulating fns makes it much more flexible and powerfull.
02:37oinksoftfor enclosing somethig in that function
02:38oinksofti usually see `stuff' defined at the same level as `some-fn', not local to `some-fn'
02:38arrdemoinksoft: so I'm not sure you can do exactly that..
02:38gunsoinksoft: mutable global state. have fun!
02:38arrdemoinksoft: but yes you can have lets enclosing defs
02:38arrdemguns: there are legitimate uses for that... memoization caches for instance
02:38oinksoftguns: sorry, stupi dexample w/ the atom
02:38oinksoftguns: i mean more like constants onl important for that function
02:39arrdemoinksoft: it'd be very strange to encapsulate them like that
02:39arrdemoinksoft: if you have some mutable state like an atom... that's almost. almost. ok.
02:39arrdemoinksoft: anything else that's constant and that you may ever want to see somewhere else..
02:39arrdemoinksoft: not kewl brah
02:40oinksofthm ok, i felt like maybe this would make for more concise definitions, shorter constant names
02:40oinksoftif it is not idiomatic then ok!
02:41gunsglobal state isn't necessarily evil; it's just that Clojure programmers often fall back to it because there is no instantiable class like thing OOTB
02:41oinksofthm i am very uncomfortable w/ using global state
02:42oinksofterlang makes it much harder to use global state
02:42gunsglobal constant data is great; my knee jerked because you were using an atom
02:42oinksoft*mutable state
02:42arrdemguns: the real insight of Clojure, and kinda the falilure of OOP imo is that you don't usually need global mutable state at all
02:42arrdemguns: some times you do need mutable state
02:43arrdemand that's fine, but usually you can get away with parameterizing everything on a single mutable parameter
02:43arrdemwhich escapes this "big mutable global singleton" antipattern
02:43arrdemand handles much more nicely in a threaded environment :D
02:43gunsarrdem: I have no quarrel with mutable state; there's no getting around it for high performance work for instance
02:44arrdemguns: and nether do I. I just contend strongly that I've only rarely seen instances where the mutable state had to be truly global scope and couldn't be managed nicer parametrically.
02:44oinksofthow do you like to structure your param lists? i do (action/description-args..., subjects)
02:44oinksoftbut some people like to put the subjects first
02:45arrdemoinksoft: typically you'll put the highest variance argument first.
02:45oinksoftah that explains why this works
02:45arrdemoinksoft: so if you have some map you're manipulating and a bunch of arguments that describe the manipulation you can use the -> macro nicely
02:46arrdemoinksoft: as-> exists because that isn't always possible... same with ->>
02:46oinksofthehe sometimes i htink i am overusing -> :)
02:46arrdemno such thing :D
02:47gunsThere's also the convention of seqable things at the end: (->> [] (map pred …) (remove pred …) …)
02:48guns*sequential things
02:48arrdemguns: this is a good case in point...
02:48arrdemguns: https://github.com/markmandel/brute/blob/master/src/brute/entity.clj#L5
02:49arrdemguns: having a global mutable def is flat out wrong.
02:49arrdemguns: see the thread... https://github.com/markmandel/brute/issues/1#issuecomment-40435084
02:50gunsyes, totally agree. I've been using stuart sierra's component library with great success
02:50arrdemheh yeah Stuart's reloaded model takes this to the extreme :P
02:51gunsarranging components together with async channels is making typical software construction really obvious
02:52gunsthen prismatic came around and delivered 70% of what I want from a type system
02:52arrdemguns: which lib.. schema?
02:52gunsit's been hard to drift away from Clojure with all this great stuff
02:52gunsarrdem: yes
02:53oinksoftclojure reminds me of perl in many ways
02:53gunsI can see that … at a meta level
02:54oinksoftthere is a strong emphasis on practicality over simplicity
02:54gunshmm?
02:54gunsthose are synonyms
02:57oinksoftguns: ##(count (ns-publics 'clojure.core))
02:57lazybotjava.lang.SecurityException: You tripped the alarm! ns-publics is bad!
02:57oinksoftah what do i know, but it's 591 here
02:58gunsthat's the whole "100s of functions on a single data structure|abstraction" perlis quote
02:58oinksoftand lots of convenient syntax over simple syntax
02:59gunsoinksoft: I'm not sure I follow that; the syntax is quite convenient, but it's also simple
02:59Platzelepnant in the room is macros
03:00gunsclojure.core stays pretty tasteful IMO
03:00AmandaCPlatz: no, it’s an elephant. Stop calling it something else, you’re hurting it’s feelings.
03:01Platzwhat happens when trying new keyboards
03:02oinksoftPlatz: yes, tha'ts another thing in clojure that reminds me of perl
03:02oinksoftPlatz: perl is a very strong language for writing DSLs
03:03AmandaCAmanda angry! Amanda… too tired to smash, maybe take a nap instead
03:04AmandaCSorry, I’m a bit loopy on sleep deprevation
03:06gunsPerl hackers have stronger stomachs than Clojurists though
03:06gunsmagic thlobals for instance
03:08Platzperl makes me think of 2600 and phrack
05:54ptcekvery noob question.. I have a string and have to pass it as Reader or InputStream instance to some java constructor... how can I do it?
06:00katratxoptcek: try http://clojure.github.io/clojure/clojure.java.io-api.html#clojure.java.io/reader
07:40luxbockhello, has anyone here got experience with using C++ in combination with Clojure? I have an application where I'd like to formulate/manipulate the inputs of a C++ program (which doesn't exist yet) from Clojure, then have the C++ program perform some heavy computing on inputs and then have the C++ output data that I'd then like to further use from Clojure
07:40luxbockI myself have no experience with C++
07:40luxbockI'm aware of https://github.com/ztellman/gloss and https://github.com/ztellman/vertigo
07:41luxbockthey talk about doing interop with C structs/libraries
07:41luxbockwould these work just as well for C++, or are there some gotchas I should be aware of?
07:50luxbocksomeone telling me that doing this is not a good idea would be good advice as well :)
09:10gfrederickstechnomancy: AND ALSO
09:11gfrederickstechnomancy: the postgres jdbc driver, when using the postgres uuid column type, returns java.util.UUID objects; so under the Technomancy Plan these objects would have to be converted to strings on every read just to maintain consistency
10:06owl-v-mm~ another day of clojure :-)
10:11owl-v-rrfrfgrfggefddfwsssssqsaqswqqwwwww2qq````````````11````111
10:11owl-v-ops
13:15krasHi folks! Is there an equivalent of consp in clojure?
13:15krasLike say cons?
13:16krasI am trying to test if something is a seq? or vector?
13:16krasI can always use an or here
13:16krasjust wondering is there is something else
13:16bbloom~colls
13:16clojurebotcolls is seqs and colls
13:16bbloom~seqs
13:16clojurebotseqs is http://www.brainonfire.net/files/seqs-and-colls/main.html
13:17bbloomkras: that page should reveal all
13:17nDuffkras, do you just want to know if it's seqable? The gotcha there is that several other things, such as strings, can also be treated as seqs.
13:18krasjust want to know if it is seq? or vector?
13:19llasramWhat are you actually trying to do with that information?
13:20krassequential? seems to be serving my purpose
13:20krasthanks for the link bbloom
13:21krasi am trying to flatten a given sequential just as an exercise
13:21krasso had to first check for this
13:22bbloomkras: as an exercise, sequential? is exactly what you want, but in practice i've found that it's almost always better to either A) treat seqs and vectors separately or B) coerce w/ seq
13:23krasbbloom: thanks I will keep that in mind
13:24krasI have come up with my own version of flatten wihtout recur ofcourse
13:24krasplease comment, appreciate your inputs
13:25krashttps://www.refheap.com/77988
13:26krasthis is the first version
13:26krasis it possible to use recur at all for flatten?
13:27bbloomkras: recur requires tail recursion and is eager. flattening is not strictly tail recursive b/c you can flatten in more than one position per call
13:28bbloomkras: your implementation is eager as well. you should try an eager version that does not use reverse (hint: vector + conj)
13:28bbloomkras: after that, try a lazy version using lazy-seq
13:29krasbbloom: when you say eager does that mean fully realizing a seq?
13:30bbloom,(take 5 (flatten (range)))
13:30clojurebot(0 1 2 3 4)
13:30bbloomkras: that takes 5 items from the result of flattening an infinite sequence
13:30bbloomkras: your code can't do that b/c it tries to walk the entire seq
13:31krasbbloom: oh ok, got it.
13:31krasI will give it a shot
13:31bbloomthere are reasons you may want an eager flatten, but generally clojure code prefers to keep seqs lazy until the end:
13:31bbloom,(into [] (take 5 (flatten (range))))
13:31clojurebot[0 1 2 3 4]
13:31bbloomthe into [] makes it eager
13:31bbloombut the internal laziness of the function pipeline is maintained
13:31kraseager eval should be defintely faster if I am correct?
13:32bbloomkras: it can be, but clojure implements some lazy optimizations such as chunking, etc
13:32mpenetluxbock: kind of, via a dll (on windows *sigh*) + a super thin jni wrapper in java, then it's just normal java interop calls from there
13:32mpenetluxbock: it is gross, but it is fast
13:35mpenetI had no acces of the c++ sources and it is crazy complex stuff (klystron simulation code) otherwise I would probably have taken another route.
13:39Jaoodbbloom: do you still love rails? ;)
13:39bbloomJaood: for what it's good at: absolutely
13:39Jaoodcame across this: http://www.brandonbloom.name/blog/2011/09/24/one-year-after-accidentally-falling-in-love-with-rails/
13:39bbloomJaood: if you've got to make a crud app in a hurry, there is no substitute
13:40Jaoodbbloom: but you don't miss ruby right? :)
13:41bbloomJaood: i much prefer clojure, if that's what you're asking :-P
13:43Jaoodbbloom: looks like rails is highly praised for that, gettting crud done quick and safe
13:46krasbbloom: a slightly improved version eliminating reverse
13:46kraswill thing about lazy seq
13:47krasthink*
13:47krashttps://www.refheap.com/77991
13:49bbloom(doc empty?) ; kras: note the seq idiom
13:49clojurebot"([coll]); Returns true if coll has no items - same as (not (seq coll)). Please use the idiom (seq x) rather than (not (empty? x))"
13:50bbloomkras: comparing against () isn't a great idea b/c nil is also an empty seq. also, generally, we prefer next over rest b/c it coerces () to nil, which tests as logical false
13:50kras,(= () nil)
13:50clojurebotfalse
13:51bbloom,(boolean nil)
13:51clojurebotfalse
13:51bbloom,(boolean ())
13:51clojurebottrue
13:51bbloom,(seq [])
13:51clojurebotnil
13:51bbloom,(rest [1])
13:51clojurebot()
13:51bbloom,(next [1])
13:51clojurebotnil
13:53krasbbloom: I realize that empty () or [] is not false like in other languages
13:53krasbut what is the problem with (= () lis)
13:54krassorry confused a litle bit
13:54llasram,(= '() (range))
13:54clojurebotfalse
13:56bbloomkras: try (flt nil [])
13:56amalloykras: writing flatten with an accumulator seems weird to me. it can't be tail recursive anyway, so why not just cons onto the result of recursion?
13:56llasramkras: I think it's two things: (a) checking exactly the property you care about, and (b) following the common language idioms to improve code readability
13:57bbloomkras: instead of (= () lst), try (nil? (seq lis))
13:58bbloomkras: which is the same as (not (seq lis)) which is empty?
13:58amalloybbloom: i assume there's some contextual reason i'm missing why (nil? (seq xs)) makes sense over (empty? xs) here?
13:58bbloomamalloy: just for illustrative purposes
14:00krasbbloom: got your point (flt nil []) gives the correct result now
14:00kraswill probably take some time to digest this info
14:02krasamalloy: could you please elaborate on what you mean by consing over the result of recursion
14:02krassorry noob here
14:02amalloykras: like (cons x (flt ...))
14:02amalloyrather than (flt ... (conj acc x))
14:02krasamalloy: oh ok, I agree,
14:03krasI started out trying tail recusion first
14:03krasthen realizes this is not possible
14:03amalloysensible
14:03krasbut that acc remianed there
14:04krasthanks a lot guys, that was really insightful discussion
14:04kraswill ponder over this for the day
14:05krastime to go bed, have a nice day
14:06bbloomthat's not a long day of pondering :-P
14:06kras:-) or should I say for the next day
14:07krasthis 4clojure is very addictive i say
14:07krasdid not realize it was so late
14:12boyscaredmight as well just keep going
14:27akazlouhi, guys, I see an "idiom" of recur-ing into the loop on the seq checking (if (next <some seq>)) which returns nil, if it is the last element in the seq, and then (next <some seq> is called for recur, of course. Is it not too expensive to do this call, and doing them 2 times? Is it better to use (not= (count <some seq>) 1) as a guard for recur instead?
14:30`szxisn't count O(n)?
14:30`szx,(doc count)
14:30clojurebot"([coll]); Returns the number of items in the collection. (count nil) returns 0. Also works on strings, arrays, and Java Collections and Maps"
14:31`szxthought i read that somewhere
14:32akazlou'szx you might right, actually maybe (next seq) is cheaper than count
14:32akazloumight be
14:32akazlouthen it would make sense to do
14:32`szxhttp://stackoverflow.com/a/1273848/318603
14:34`szxakazlou: yeah, i'm sure there's a good reason though i can't say for sure i know what it is
14:36akazlou,(map #(instance? clojure.lang.Counted %1) [[] '() {} (seq [])]
14:36clojurebot#<RuntimeException java.lang.RuntimeException: EOF while reading>
14:36akazlou,(map #(instance? clojure.lang.Counted %1) [[] '() {} (seq [])])
14:36clojurebot(true true true false)
14:37akazlouso map, vector and list implements Counted, but seq not
14:38akazloumy bad
14:38akazlou(map #(instance? clojure.lang.Counted %1) [[] '() {} (seq [])]
14:38akazlou,(map #(instance? clojure.lang.Counted %1) [[] '() {} (seq [1])]
14:38clojurebot#<RuntimeException java.lang.RuntimeException: EOF while reading>
14:38akazlou,(map #(instance? clojure.lang.Counted %1) [[] '() {} (seq [1])])
14:38clojurebot(true true true true)
14:39akazlouall of them true, just seq on empty list is nil
14:39`szxinteresting
14:39akazlouso, count is O(1) for all of them in that case?
14:39llasramakazlou: NB that `seq` on a vector is a special case
14:39llasram,(type (seq [1]))
14:39clojurebotclojure.lang.PersistentVector$ChunkedSeq
14:40llasram,(.count (seq [1]))
14:40clojurebot1
14:42dbaschI just wrote a few Bitcoin base58 encoding/decoding functions, maybe I should put them on github. Anyone care to review them?
14:42dbaschhttps://www.refheap.com/77995
14:43akazlou@llasram, thank you for mentioning this
14:55amalloyllasram: in what way is seq'ing a vector a special case?
14:58llasramamalloy: The `seq` of a vector is `counted?`, but seqs in general are not necessarily
15:01amalloymmmm. i don't know that i'd call that a special case - it implies to me that there's something inside of count/Counted that treats vector-seqs specially somehow. but vector's seq is just one of N sequences that does implement Counted
15:03amalloyseq on a map is counted too, and same for a list (ha ha). and you can make arbitrary instances of Counted yourself
15:03llasramThat's fair. I just noticed a risk of someone inferring all seqs to be Counted. I trying to just clarify that the Vector-specific seq implementation specifically implements Counted
15:04llasramBut that isn't a guaranteed property of seqs
15:18gfredericksokay so I think I'm going to try to write a multiplexing nrepl middleware
15:19gfredericksQ: should I call it muxrepl or mrepl or something else?
15:20whiloi have some exceptions in my test-output as well as sometimes on runtime (nrepl-server output in emacs), how do i turn on stacktraces? i tried to put the code in a try-catch block, but this hasn't worked so far. it is run in core.asyncs threadpool in these cases
15:20llasramgfredericks: What's it going to multiplex?
15:21hiredmangfredericks: manifold
15:21llasramwhilo: Are you not getting the full traces in your *nrepl-server* buffer?
15:21whilonope
15:21llasramHmm. Odd
15:21whilojust the error message
15:22whilolike: #<NullPointerException java.lang.NullPointerException>
15:22llasramWeird. That looks like something is just `pr`ing the exception object
15:22gfredericksllasram: sessions
15:23gfredericksllasram: biggest immediate win: backgrounding a long-running expression while it's running
15:23whilollasram: yes
15:23gfredericksllasram: but I also want to use it for implementing a debug-repl
15:24akazlouthere is (counted?) in clojure
15:24akazlou,(doc counted?)
15:24clojurebot"([coll]); Returns true if coll implements count in constant time"
15:24llasramwhilo: Wheeeelp. That's not normal. Hmm. This is tricky :-)
15:24llasramgfredericks: I've already got a solution for that -- (def *result (future ...)) ;-)
15:25llasramgfredericks: Oh, so when the debugger gets invoked, it starts another session...?
15:25gfrederickshiredman: is that a ztellman joke?
15:26hiredmangfredericks: no, does he already have a library called manifold?
15:26gfredericksllasram: A) this is for _after_ the fact
15:26whilosome exceptions get thrown properly with stacktraces, so i assume it is core.async specific. not sure though
15:26gfrederickshiredman: yeah
15:26hiredmanoh, well, not that then
15:26gfredericksllasram: and yeah, the debug-repl starts another session which you can switch back and forth from
15:26gfrederickshiredman: I didn't know that though, and liked the idea
15:26llasramgfredericks: Neat
15:26dbaschwhilo:it’s probably this: https://github.com/clojure/core.async/blob/76b25bf91c670b0c3542ed9cb687ff29fb2183a7/src/main/clojure/clojure/core/async/impl/exec/threadpool.clj#L33
15:26gfredericksllasram: I already have something better than futures actually, but it still requires forethought
15:27whilodbasch: very well, thx
15:27whilowhy is it println'ed? is there a idiomatic way to tune that?
15:28llasramwhilo, dbasch: Ouch. That's not very friendly
15:29whiloi think it should default to the stacktrace, but that still doesn't make it tunable (don't know enough about logging yet, to say what was appropriate)
15:29hiredmangfredericks: how about manigfeald, which is, according to google, the old english word manifold comes from
15:29hiredmanlots of google juice, no idea how to pronounce it
15:29gfrederickshiredman: ha
15:29dbaschwhilo: ask Rich Hickey, or file an issue / pull request
15:29llasramNot a pull request
15:30llasramBut yeah, check to see if there's an issue already on the core.async JIRA
15:30whilook. people seem to be programming fault free, when i am the first to have a problem with this XD
15:30llasramThat seems like the worst possible behavior for it, short of silently swallowing the exception
15:30hiredmanwhilo: the first thing to do is to see if it is repropducible outside of lein repl, cider, or whatever tools
15:31whilolein test reproduces it as well
15:31whiloor lein run
15:32llasramhiredman: The linked core.async code just calls `println` on any exceptions thrown from async tasks
15:32llasramSo no possibility of stacktraces ever
15:32hiredmanah
15:32hiredmanwell, what should it do?
15:32llasramPrint a stack trace?
15:32hiredmanto where?
15:33llasramAnywhere :-) I mean, right now it unilaterally prints something useless to *out*
15:33llasramIt seems like an incremental improvement would be to print something useful to *out*
15:33llasramThen go from there
15:34hiredmanllasram: I dunno, it seems like there is no best solution, so the best thing is for the user to decide the behaviour they want, and there is a way to do that, put a try/catch in your go expressions that prints a stacktrace
15:34whiloprinting stacktrace fixes my issue :-)
15:35whilohiredman: that didn't work for me
15:35whilohiredman: weren't they outside this try-catch block?
15:35dbaschhiredman: see the code: https://github.com/clojure/core.async/blob/76b25bf91c670b0c3542ed9cb687ff29fb2183a7/src/main/clojure/clojure/core/async/impl/exec/threadpool.clj#L33
15:35whilomuch better, now i only feel half blind :-)
15:36hiredmandbasch: I see it
15:36dbaschno question that printing a stacktrace would be better than .toString
15:36hiredmandbasch: but what if I don't want to print the stacktrace
15:37dbaschhiredman: what if you don’t want to print .toString?
15:37dbaschsame thing
15:37hiredmanwhilo: I doubt that, my guess would be you put the try/catch in the wrong place then
15:37dbaschbut if you choose one, stacktrace is a more useful default
15:37hiredmandbasch: sure, I would argue it should do neither
15:37hiredmandbasch: it looks like the commit that introduced that left debugging printlns in a number of places :/
15:38llasramhiredman: Ohhhh, maybe that's what they are. I just noticed that
15:38llasramThere's also this issue http://dev.clojure.org/jira/browse/ASYNC-61 which seems to reflect the behavior prior to that commit
15:40hiredmanthe core.async code seems kind of like the wild west, commits landing that doen't seem to reference issues in jira, debug printlns being left in seems to indicate little or no code review
15:41dbaschthe comment at the end is right, it seems that the fix was a quick hack
15:41llasramhiredman: Which makes me sad :-/
15:42hiredmanllasram: yep, maybe some day it will settle down, it is still "alpha"
15:42llasramAnd no tbaldridge ATM to grill about it :-)
15:42hiredmanllasram: I am sure he would point to the aplha designator
15:42llasramProbably so
15:43dbaschbefore coding anything, it would be worth thinking about how logging should work for core.async and then implement that
15:44dbaschlogging has been one of the most annoying parts of java since forever
15:44whilothat indeed was interesting to me as well, as i need to address logging with it soon as well
15:44hiredmanclojure.tools.logging words fine
15:44hiredmanworks
15:44llasram(inc hiredman)
15:44lazybot⇒ 44
15:45dbaschhiredman: but core.async doesn’t use it :)
15:45hiredmandbasch: right, logging is your concern as a consumer of core.async
15:46hiredmancore.async shouldn't dictate how you do logging
15:48llasramSomeone needs to create an SLF4J backend for timbre, then the great cycle of JVM logging will be complete
15:50sveriHi, while exploring om I just want to make sure that my thinking is correct. Executing this code: http://pastebin.com/kt5Nes8T it happens that the output "render state" is printed twice to the js console. The first time because the render-state function is called with an unitialized app state and the second time because and the second time because "init-state" of the "text" function was called and changed the application state. This is expec
15:53ToBeReplacedllasram: do you use timbre?
15:54llasramToBeReplaced: Nope. tool.logging
15:54ToBeReplacedllasram: yeah, same... wondering why someone would use it instead
15:55llasramToBeReplaced: JVM logging is complex enough -- I don't see how adding an entirely new language-specific logging library makes it better
15:56llasramI've heard people say they couldn't get tools.logging + <Java logging library> configured properly, while timbre is apparently much easier to setup
15:56llasramAnd also cite the lack of XML
15:57llasramOTOH, I just use slfj+log4j w/ the same short ->stderr property file everywhere, so YMMV
15:58ToBeReplacedllasram: i guess i can understand that... though that's a little weird b/c if i was starting a project from scratch and thus got to integrate the logging lib of my choice it'd be logback, and not only is their xml config sane, but you can configure it with code instead if you wish
15:59ToBeReplacedllasram: idk i shoudl probably stop there... i get a bad taste in my mouth with any of the clojurewerkz libraries, and i already got myself band from one of their repos ;)
15:59ToBeReplacedbanned*
15:59llasramI don't think timbre is ClojureWerkz. Just "supports their goals"
16:00hiredmanfriend of my enemy, etc
16:00ToBeReplacedi got bannedd from a taoensso library, heh
16:00llasramAhh
16:00llasramI was just thinking the Clojure community needed some more drama
16:00llasramLiven things up a bit
16:01hiredmando I want to use a library with goals? what if it doesn't match my lifestyle?
16:02llasramWhat if you grow apart over time, and realize some day that you want to structure your APIs entirely differently?
16:03hiredmanwhat if I "link" against the api, but I am not "linking" against the api?
16:04llasramYou can try spicing things up with a compatibility shim!
16:05ToBeReplacedi started putting together a list a while back of clojure libs i'm happy to use/ship, and i found it's actually really small outside of org.clojure
16:05ToBeReplacedif either of you (or onlookers) have a similar list i'd be interested in seeing it
16:08llasramHmm, interesting. There's definitely some de facto standard stuff I use everywhere (ring, cheshire), but yeah -- not a lot
16:09whodidthishow do i convert these javascript object properties, kind of like arrays, into vectors http://pastebin.com/vdqxdGZx
16:11llasramToBeReplaced: I'm going to chalk it up to the Lisp curse :-)
16:12ToBeReplacedllasram: as a non-web developer, my forays into web development on clojure have been pretty rocky -- i found that the middleware abstraction makes it awfully hard to follow RFC 2616; is that false? does it matter?
16:12amalloywhat does it even mean to be banned from a repo, ToBeReplaced?
16:13ToBeReplacedas basic example -- distinguishing between 405 and 404 using a clojure routing solution seems to be tricky
16:13llasramToBeReplaced: I'm the wrong person to ask. We write a lot of internal JSON APIs, but nothing that needs to play nicely with a very wide world
16:13ToBeReplacedamalloy: when i try to post comments in issues i get informed i've been blocked from the repository
16:13amalloyhuh. i didn't even know that was possible
16:14amalloybrb gonna ban some folks from my repos, for science
16:14llasramSWEET
16:14vermawhen I am developing stuff using composure I want to refer to a different template instead of the one I use for production (basically the template name that goes into my render call), how can I detect if I am in dev or prod mode during runtime?
16:14dbaschwhodidthis: https://github.com/clojure/clojurescript/blob/master/src/cljs/cljs/core.cljs#L7356
16:15ToBeReplacedverma: consider using JVM options and accessing via System/getProperty
16:15amalloyhuh. i can't find that option. i wonder if they asked github support specially
16:15llasramverma: Alternatively, consider passing in different arguments the function constructing your handler chain for "dev" vs "production"
16:16llasramMy experience is that trying to have stuff which automatically acts differently based on different "environments" creates a lot of hassle
16:16llasramEspecially e.g. around running "test" tests within your "dev" REPL
16:18ToBeReplacedamalloy: https://help.github.com/articles/blocking-a-user
16:18vermaToBeReplaced, llasram, got it, thanks :)
16:18coventry`verma: You might find carica useful for distinguishing dev from production. Environment variables and System/getenv work too.
16:19llasramStops them from forking? Wow
16:19amalloyllasram: well, with a fork of a repo you can make yourself a bit of a nuisance
16:19llasramHow so?
16:19vermacoventry`, thanks, I think I will go the system env route I think
16:19amalloyeg, commit a hundred things that say: "Fixes #121. Repo owner is a nazi."
16:20amalloythose show up in the discussion thread of #121 in the base repo
16:20llasramOh, geez. I didn't realize that
16:20ToBeReplacedverma: llasram's take is better/more correct... generally pass things as arguments, i use jvm-opts as the outside configuration that can't be known (ex. "where is logging gonna go?)
16:20amalloybut of course you can still clone the repo and re-push it as your own. the code is still shared, you're just not socially connected to upstream
16:20llasramSure
16:21whodidthisdbasch: returns the object :( maybe ill figure out something else
16:21llasramOh, humans
16:36vermaToBeReplaced, hmmm, sounds good, taking a look
16:37vermaToBeReplaced, nice, so jvm-opts are supplied to jvm that lein run uses, but won't be there when I create and distribute my standalone jar, nice
16:39justin_smithyou can't specify jvm opts in a jar, it simply doesn't work that way
16:40vermajustin_smith, yeah I know, what I meant was that they will be absent
16:40justin_smithI wasn't sure if you were being sarcastic
16:41verma:)
16:41`szxwith datomic, does it make sense at all to add attributes on the fly (i.e. user-generated attributes, over the lifetime of an application) or is that something you're not supposed to do?
16:42`szxi guess #datomic would be a better place to ask
16:42`szxheh
16:42vermajusting_smith, don't think I was being sarcastic, may be not a very coherent thought on my part :)
17:02DomKMIs there a protocol for clojure.core/contains?
17:04amalloyDomKM: an interface
17:04amalloyshould be clojure.lang.ILookup iirc
17:04DomKMthanks amalloy
17:09KrajsnickCould someone explain me how the different Clojure fib functions I try and time with clojures time function runs a fib(45) on 0.2 msec while node.js does it in 16 secs, and ruby... dont even wanna start a fib(45)
17:09KrajsnickHow can the Clojure fib function be so fast?
17:09ivanfibonacci can be computed sequentially
17:10justin_smithyeah, it's probably using the memoizing algorithm
17:10Krajsnickone of the ones I tried used a memoizing function yes
17:11KrajsnickSo basically the other language just does it linnear, while clojure kinds of jump from one fib number to the next fib to the next
17:12justin_smithdo you have links to the various implementations?
17:12Krajsnicksure
17:12Krajsnickhttp://stackoverflow.com/questions/8939970/a-recursive-fibonacci-function-in-clojure
17:12KrajsnickI used a couple of these
17:12Krajsnickall of them gives me answer instantly
17:13Krajsnicknow I found one that doesn't, and was 2-3 seconds slower than node
17:13Krajsnickhttp://intothewebs.tumblr.com/post/45073028163/a-little-bit-of-clojure the first fib function
17:20justin_smithyeah, that one is not memoizing, and also not tail recursive
17:25persesis there anybody using titanum graph lib?
17:41justin_smithperses: I've been meaning to try it out
17:42DomKMamalloy: How would you create a type that implements clojure.core/contains? It looks like ILookup is for clojure.core/get
17:42justin_smithDomKM: I think if you implement ILookup you get bot get and contains?
17:43justin_smithsince get also needs to know whether a value is present or not
17:43DomKMjava.lang.IllegalArgumentException: contains? not supported on type:
17:43DomKMbut get works fine
17:43coventryWhat's a clean way to express a test.check generator which just returns the values from a zero-arity function? I'm looking for something like (gen/fmap (fn [_] (my-fn)) gen/int).
17:43justin_smithDomKM: OH, I don't know then
17:44reiddrapercoventry: hmm, is this a pure function?
17:44amalloyyeah, apparently contains? is a bit weird
17:45amalloyyou need to implement one of: Associative, IPersistentSet, Set, or Map
17:45amalloywhich doesn't seem very nice to me
17:45reiddrapercoventry: you can use gen/return to create a 'constantly' generator
17:46coventryreiddraper: No, I'm trying to generate objects with a lot of shared structure, and my-fn will be pulling objects to be reused from a set in an atom.
17:46reiddrapercoventry: so will that be adding randomness that is not controlled by test.check?
17:46reiddrapercoventry: if so, I would recommend against that if possible
17:47DomKMamalloy: Set makes sense for my use case. Do you know the protocol/interface for it?
17:47amalloyi listed the names of all the interfaces just above
17:47amalloyjava.util.Set, or clojure.lang.IPersistentSet
17:48coventryreiddraper: That was the idea, though I'm open to suggestions for other ways to construct objects with lots of structural sharing.
17:48coventryAh, you don't want to add extra randomness because it breaks shrinking, I guess?
17:48amalloycoventry: what about a vector that contains all the objects you want to share, and use like one-of to choose from its items?
17:49DomKMthanks
17:49reiddrapercoventry: what's wrong with creating generators the 'normal' way?
17:49reiddraperi'm not sure i follow how structural sharing is relevant here
17:50coventryI want to make tests for an object serializer which is aware of structural sharing.
17:51reiddraperso, if you serialize X, and then later serialize Y, which shares some structure, it has some different behavior than normal serialization would?
17:52coventryreiddraper: No, I want the serialization of [X X X X] to only contain one serialization of X.
17:53reiddraperand right now you verify that across different test runs? Or within a single test?
17:53coventry(This is for cljs, BTW. I imagine there's already an option for this in java.)
17:54reiddrapercoventry: from what i've heard so far this wouldn't be easier/harder in clj/cljs
17:54coventryreiddraper: Right now, I only have the most basic test: (let [foo [1 2] bar [1 2] composite [foo bar foo]] (test that serialization only has one copy of foo))
17:56reiddrapercoventry: I would recommend writing generators that are likely to have quite a bit of duplication/sharing, and then, within a single test run/iteration, check that your property of only representing that object once, works correctly
17:56reiddraperthat way you don't need to use a stateful atom to 'remember' things across test runs
17:57coventryYes, the shrinking property is worth preserving, thanks for pointing that out.
17:57reiddraperand reproducibility
17:58reiddraperdespite being a 'random' testing tool, test.check has provisions for repeating the exact same random test
17:59coventryHmm, I wouldn't have expected that to be a problem, as long as the state atom is created fresh per-run, and the test runs in a single thread.
18:09coventryCan I use gen/bind recursively?
18:10reiddrapercoventry: yes, it's quite common to
18:11coventryGreat, are there any examples you can easily point me to?
18:16coventryIn a recursive gen/bind, how can I signal that the recursion should stop? The recursive generator at https://github.com/clojure/test.check/blob/master/doc/intro.md#recursive-generators does it with a function which takes a size argument. Is there a way to do a bind which is size-aware?
18:18akhudekRegarding om, consider rendering a large vector of items. If you remove one item from the middle and add it back to the end, will om/react rerender the entire list becasue the index of each item has changed?
18:19coventryakhudek: Any change to the state will trigger a re-render, but components which have views into specific subtrees via cursors will check whether they should re-render by checking whether their subtrees are (identical?). So it depends on the state data you're passing to your components.
18:20coventryakhudek: https://github.com/swannodette/om/blob/master/src/om/core.cljs#L239
18:25persesjustin_smith: still there?
18:25justin_smithyes, hi
18:26persesjustin_smith: hi, so you have tried it yet?
18:26justin_smithnot really, no - but if you have a problem or question it can't hurt to ask
18:27persesjustin_smith: how can i add vertex uniquely to the graph?
18:28persesif i did (tg/transact! (tv/create! {:name "hello"}) (tv/create! {:name "hello"}) (tv/create! {:name "hello"})), will add 3 vertices
18:28persesbut the logic is it should be one?
18:28justin_smithtitanium.clojurewerkz.org/articles/vertices.html unique-upsert looks like it may be the thing?
18:28justin_smithyeah, you want the unique-upsert! function for that (it meantions it right after create! in the docs I linked)
18:29persesah so i should replace tv/create! to tv/unique-upsert! ?
18:30justin_smithI think so, but only based on reading the docs just now - it may be more complex than that
18:30justin_smithcan't hurt to try
18:30justin_smithoh, upsert needs a location
18:32coventryreiddraper: NM, I see how to do it now.
18:32reiddrapercoventry: cool
18:32coventryThanks for your help.
18:37akhudekcoventry: Thanks, I get that much, but I’m tyring to debug a performance problem and suspect that it’s actually updating the whole list since I see updateDom as taking the most time in a profile. I’m trying the react dev tools and each item in the list is encolosed in an om wrapper cursor that contains the index in it’s props.
18:40coventryakhudek: When I ran into this problem, I was able to verify that suspicion by sticking a (js/console.log (pr-str (element identifier))) in the render method.
18:42coventryakhudek: Just to be clear, when you say "each item in the list is enclosed in an om wrapper cursor," you mean that the components associated with the list elements get the element data via an om cursor, right?
18:45akhudekeach component of the list is definitely an om cursor. The structure is a bunch of maps in a large vector. This vector is sorted and then build-all is called on the resulting list. Thus each individual item (a map) should still be a cursor. I can see that in the dev tools clearly. But there is an “unknown” react component around each item that seems to be part of om internals.
18:46akhudekcoventry: I just tried the console log trick, and it definitely calls render on each item of the list for every update. It’s unfortunately frozen up now though. There are over 2000 items and I guess the logging could not handle the output.
18:49akhudekcoventry: also, calling render doesn’t actually mean that it will update the dom, right? or does it?
18:50coventryakhudek: No, my understanding is that the actual dom element will not be updated unless the output of the render method has changed.
18:53coventryakhudek: However, it is surprising that the render method of the element components are being called at all, since their values should be identiical to their previous values.
18:54akhudekcoventry: yeah, I didn’t think it should be calling render either.
19:16coventryI'm not sure how to go about debugging this test.check generator. It's giving me an NPE with a stack trace which doesn't mention my namespace, and none of my debugging printlns are producing output. Any suggestions? https://www.refheap.com/78021
19:18dbaschwhat’s the best / usual way to tell a cljs app that it’s running in production or dev?
19:19akhudekcoventry: figured out why it’s calling render at least. The items are = but not identical.
19:20coventryakhudek: Oh, it wasn't just a rearrangement of the list? That makes sense.
19:22coventrydbasch: You can use a macro to do it whatever way you do it in clj, at compile time.
19:27akhudekcoventry: oh man, implementing a custom should-update that swaps the identical? check for = completely fixed the performance problems.
19:28coventryakhudek: Yeah, I had a similar experience.
19:30akhudekI’m curious about dnolen_’s thoughts on this.
19:31coventryWell, an equality check is expensive. The whole reason om is more performant than react is that it does identity checks.
19:31dbaschcoventry: In clj I use the jvm environment, but I’ll look into carica
19:32coventrydbasch: Not sure why, but wiser people than me were saying earlier that jvm-opts is the way to go.
19:33dbaschcoventry: ok, but what do you do in the browser?
19:33dnolen_akhudek: as a general rule that will slow things down in Om
19:34dnolen_akhudek: at least in the current version anyway, working on some things that will allow us to switch to = over identical?
19:34coventrydbasch: You make a java macro, which you call at compile time in your clojurescript.
19:34dbaschcoventry: you mean a clj macro that reads from the jvm environment, I assume
19:35coventrydbasch: yeah, like (defmacro prod? [] (System/getenv "PROD"))
19:37justin_smithcoventry: but that would check whether compilation was happening where PROD is set - it could cause unexpected results with uberjar creation
19:38justin_smithif aot is involved, at least
19:38dbaschcoventry: it would be better to do something with the dev/prod profiles in cljsbuild
19:41coventrydbasch: You're right.
19:41coventryjustin_smith: I was just giving an example of how to get something from the outside environment into cljs.
19:41justin_smithahh, ok
19:42dbaschcoventry: the first thing that occurs to me is to have a different output name and check the running script name, but that’s *really* ugly
19:43frustration-statI am trying to load clojure.tools.cli 0.3.1 in a repl, but no matter which method I use, the version built-in to my clojure version is used, which is older than 0.3.1
19:43justin_smithhave the app create a file recording its PID and metadata about itself?
19:43coventrydbasch: If you want to do that, you can put something like :profiles {:prod {:resource-paths ["config/prod"]} :dev {:resource-paths ["config/dev"]}} in your project.clj, and use carica. (This is what we do, actually.)
19:44dbaschcoventry: yes, I cannot think of a better option
19:45frustration-statie: (use '[clojure.tools.cli :as cli :only [parse-opts]]) => IllegalAccessError parse-opts does not exist clojure.core/refer (core.clj:3849)
19:45frustration-stat
19:47dbaschfrustration-stat: what’s your project.clj?
19:48frustration-statdbasch: i've tried with [org.clojure/tools.cli "0.3.1"] in project.clj and i've also tried with lein-try
19:48frustration-statsame result
19:48akhudekdnolen_: I guess our use case is somewhat pathelogically bad for om updates when using identical. We do a fair amount of data manipulation prior to feeding data into components. E.g. for each item in a list, assoc a sublist of related data. This is because our base data is a collection of automatically updated materialized sql queries. We handle one to many or many to many relationships by composing data in the client.
19:49frustration-statdbasch: the only way i've gotten it to work is to clone the github repo and run a lein repl from the checkout
19:49dnolen_akhudek: sure, IShouldUpdate is there for a reason
19:50dnolen_akhudek: however it important that you understand the default implementation (or copy and paste it and just change the bit you need)
19:50dbaschfrustration-stat: I just created a blank project with clojure 1.5.1 and it works fine
19:50dbaschfrustration-stat: what clojure are you using?
19:51akhudekdnolen_: yeah, I’ve copied and modifed the cond here https://github.com/swannodette/om/blob/master/src/om/core.cljs#L239
19:51frustration-statdbasch: i'vew tried both 1.5.1 and 1.6.0
19:51dbaschfrustration-stat: (same with 1.6.0)
19:51akhudekdnolen_: by the way, I did create a set cursor implementation, but sadly found that it doesn’t work well as a backing for stateful compoenents
19:51dbaschfrustration-stat: there’s probably a dependency conflict, you should post your project.clj or run lein deps :tree
19:52coventryakhudek: How does it break?
19:52dnolen_akhudek: just note using your should-update breaks om/set-state! for that component for now (I'm assuming your using :ctor option to do this)
19:52dnolen_akhudek: care to elaborate on the set cursor? not really following
19:54frustration-statdbasch: i just tried a blank project, must be a conflict, checking :tree, thanks
19:55akhudekdnolen_: I found that set-state uses the path to the cursor in it’s call to assoc. This would be fine, but it also seems to represent state using a copy of the data? In any case, I ended up getting errors because you cannot assoc through a set.
19:55akhudekhold on and I’ll link the implemenation, it’s just a small modification to mapcursor
19:56akhudekhttps://github.com/akhudek/om/blob/set-cursor/src/om/core.cljs#L415
19:56akhudekAlso modified to-cursor to be aware of sets.
19:56akhudekother than the state, it seems to work
20:00dnolen_akhudek: yeah another issue that will be solved by what I'm working on
20:02akhudekdnolen_: ok, sounds good. Is there documentation for the :ctor option you mentioned above? I’m not familiar with it.
20:02dnolen_akhudek: you can supply an alternative backing React component, an alternative to pure
20:02coventry,(let [len 1e7 a (doall (range len)) b (doall (range len))] (time (= a b)))
20:02clojurebot#<OutOfMemoryError java.lang.OutOfMemoryError: Java heap space>
20:03coventry,(let [len 1e5 a (doall (range len)) b (doall (range len))] (time (= a b)))
20:03clojurebot"Elapsed time: 65.673784 msecs"\ntrue
20:03coventry(let [len 1e5 a (range len) b (range len)] (time (= a b)))
20:03coventry,(let [len 1e5 a (range len) b (range len)] (time (= a b)))
20:03clojurebot"Elapsed time: 68.550158 msecs"\ntrue
20:04dnolen_akhudek: it's documented in build's docstring but there's not an example yet beyond the `harmful` example in the repo
20:04coventryWhy does this equality check take almost the same time whether or not I force the structures with doall before the clock starts?
20:05coventry(With length 1e7 on a real machine, doall only knocks off about 20% of the time)
20:05dnolen_coventry: ranges aren't lazy seqs
20:05akhudekdnolen_: ok, thanks, I’ll read up on that
20:07coventry,(class (range 10))
20:07clojurebotclojure.lang.LazySeq
20:09dnolen_coventry: oh hmm, perhaps getting confused because there's a Range.java and Range deftype in ClojureScript
20:13Bronsadnolen_: looks like clojure's range uses chunked buffers
20:13dnolen_Bronsa: yeah
20:14BronsaRange.java looks exactly like cljs Range OTOH
20:15dnolen_Bronsa: yeah chunked buffers came late to ClojureScript
20:15coventryEven with chunking, I would have expected the object creation to be more expensive than the equality check. Am I just wrong about that?
20:58amalloycoventry: i would expect that too, but i could imagine it being wrong. object allocation and arithmetic are both very cheap, and perhaps equality is expensive because it has to double-check types over and over. have you tried in a more careful benchmark, eg via criterium?
21:00coventryNo, that's a good idea, although I actually came across this in cljs, and that's where I'm really interested in the question. Not sure whether you need to take the same care when benchmarking javascript, have to do a bit of research.
21:09amalloyyou need to take care when benchmarking anything. small sample sizes in unrealistic situations don't tell the real story
21:09TravisDI am really not trying to troll. Is there a performance improvement to using scala over clojure?
21:13krascame up with the following code for my own version of flatten https://www.refheap.com/78032
21:13krasI am trying to make it do lazy eval
21:14coventryamalloy: Thanks, it looks like the answer is "use jsperf.com". Sounds easy...
21:14kraslooks like the trail and error method of inserting lazy-seq on recursion calls is not helping
21:14krasany suggestions?
21:15coventryMaybe http://clojuredocs.org/clojure_core/1.2.0/clojure.core/lazy-cat ?
21:16jdkealyI've been confused with compojure and jetty. I don't know how to get this :title attribute from a request payload. I have added wrap-params to my routes... Additionally, when I try this route, it seems i need to restart my server to see any changes take effect. https://gist.github.com/jdkealy/11129546
21:18amalloyyeah, instead of into, just use concat
21:18amalloyand wrap the whole thing in a lazy-seq
21:19kras,(concat ["a"] ["b"])
21:19clojurebot("a" "b")
21:19ivanis there a try/catch/else macro somewhere?
21:19krasamalloy: coventry: thanks for the clue
21:20amalloyivan: what would the else do?
21:20ivanamalloy: run something if no exception was caught
21:21amalloythat's just...more stuff after the try
21:21amalloy(try (a) (b) (catch))
21:21amalloyunless you really really don't want to catch them in b, i guess
21:21ivanno, because then the catch covers (b)
21:21ivanright
21:21ivanPython has this :)
21:22krashurray, (take 5 (flt (range))) works now with stackoverflow :-)
21:23krasI meant without*
21:26coventryI've got a generator which produces deeply nested structures with extensive structural sharing, but it's awfully slow... any suggestions for ways to speed it up? https://www.refheap.com/78033
21:27coventry(Response when I mixed that message to ##javascript: "<j201> THE PARENS THEY BURN")
21:29krasany suggestions on whom to follow on 4clojure's solutions list
21:29coventrydaowen is the shit.
21:32ivanI feel like Clojure code could use some vertical whitespace outside of cond
21:33krascoventry: real cool man, he just did it in one line and its more readable
21:33krasthanks for the suggestion
21:33justin_smithivan: -> / ->> lead to good vertical whitespace
21:34ivanit does? my imagination is failing me
21:34justin_smithwait, I could be misunderstanding you
21:34clojurebotGabh mo leithscéal?
21:35justin_smithhow does cond lead to good vertical whitespace?
21:35Frozenlockcoventry: I feel the lack of parens disturbing. It's like driving at high speed without a seat belt.
21:36Frozenlocker.. "the lack of parens is disturbing"
21:36ivanjustin_smith: blank lines between things
21:37justin_smithivan: blank lines within a form is not good style as far as I am concerned, but you can put in line breaks anywhere you want
21:39justin_smithI have a coworker who pretty much puts empty lines in his defns whereever
21:39justin_smithit kind of breaks how I use emacs though
21:41fuJiinnoob question - anybody building webapps use futures for parallel db calls?
21:42fuJiinanything to watch out for when doing this?
21:42justin_smithit may not help much if the parallel calls are to the same db
21:43coventryjustin_smith: How does that break emacs?
21:44justin_smithit breaks the "defun is separated by blank lines" assumption used by many of my favorite keybindings
21:44krashow do I know if a function evals lazily?
21:44fuJiinits the same db, but so far its shaved a full second off response times
21:44justin_smithcoventry: not "break" really as much as make them not be as useful
21:44coventryOh, OK.
21:44krasthe mapcat function doc doesn't say anything about laziness but looks like it evals lazily
21:45justin_smithkras: the way to check is the type of the output
21:45justin_smith,(class (mapcat identity (range)))
21:45clojurebotclojure.lang.LazySeq
21:45justin_smiththat's how you know
21:46krasjustin_smith: thank you
22:17krasI have written my own version of max as https://www.refheap.com/78039
22:17krasthis works fine in my repl
22:17krasbut gives an error on 4clojure
22:18krasclojure.lang.ArityException: Wrong number of args (1) passed to: core$partial
22:27danlamannacan anyone tell me why the first works and the second doesn't? https://gist.github.com/danlamanna/11130607
22:28owl-v-does .isFile returns boolean?
22:29`szxdanlamanna: because it's a java method, not a function?
22:29`szx,(doc memfn)
22:29clojurebot"([name & args]); Expands into code that creates a fn that expects to be passed an object and any args and calls the named instance method on the object passing the args. Use when you want to treat a Java method as a first-class fn. name may be type-hinted with the method receiver's type in order to avoid reflective calls."
22:29`szxdanlamanna: ^
22:29danlamannaahh
22:31Bronsadanlamanna: methods are not first-class like functions, you have to wrap method calls in fns if you need to use them as such.
22:31owl-v-(not= (filter (method) (stuff)) (filter (boolean) (stuff)) )
22:31dbaschdanlamanna: you can wrap it like this: #(.isFile %)
22:36justin_smithit appears kras left (if you renamed I don't see those messages right now), the problem with mymax is that (partial mymax) should be #(partial mymax %&)
22:38justin_smithbut really if you are using reduce already there is only need for the one and two arg versions (as a helper fn) plus a wrapper to do the reduce
22:46owl-v-is (defn fun [] (fun)) same as (defn fun [] (recur)) ???
22:46lazybotowl-v-: How could that be wrong?
22:47justin_smithowl-v-: there is no such thing as implicit tail recursion in clojure
22:47justin_smithso they are not the same
22:47justin_smith*implicit tail recursion optimization
22:49owl-v- (defn fun [] (fun)) < (defn fun [] (recur)) ???
22:49lazybotowl-v-: How could that be wrong?
22:49owl-v-lol. lazybot~
22:49justin_smithwell the latter is optimized
22:49justin_smithusually you want that
22:52owl-v-justin_smith: thanks
22:53bbloomapparently three question marks is wildly inappropriate conduct, says lazybot ???
22:53lazybotbbloom: Yes, 100% for sure.
22:53bbloom(inc lazybot)
22:53lazybot⇒ 25
22:53justin_smithwhat about 4 question marks ????
22:53justin_smithhmm ???
22:53lazybotjustin_smith: Oh, absolutely.
22:54bbloomor an interrobang ‽
22:54owl-v-what does '???' do ???
22:54lazybotowl-v-: Oh, absolutely.
22:54bbloomit does stuff ‽‽‽
22:54agarman,(apply str (repeat 3 \?)))
22:54clojurebot"???"
22:55bbloomagarman: the bots ignore each other
22:55bbloom,(println "???")
22:55clojurebot???\n
22:55bbloom,(print "???")
22:55clojurebot???
22:55bbloom???
22:55lazybotbbloom: Yes, 100% for sure.
22:56owl-v-lazybot accepts only user message ???
22:56lazybotowl-v-: How could that be wrong?
22:58schlegel???
22:58lazybotschlegel: Oh, absolutely.
22:58schlegelWhat's the point
22:58owl-v-,(prn "yes ???")
22:58clojurebot"yes ???"\n
22:58owl-v-,(print "yes ???")
22:58clojurebotyes ???
22:58justin_smith,'???
22:59clojurebot???
22:59lazybotjustin_smith: How could that be wrong?
22:59owl-v-justin_smith: u did it!
22:59schlegelNo it replied to him
23:00justin_smith,(:q '{:q ??? :a !!!})
23:00clojurebot???
23:00owl-v-,'final boss ???
23:00clojurebotfinal
23:00lazybotowl-v-: Oh, absolutely.
23:00owl-v-oh
23:01owl-v-,(print "/NICK clojurebot2")
23:01clojurebot/NICK clojurebot2
23:02owl-v-,(print "???")
23:02clojurebot???
23:02owl-v-bot can't change nickname???
23:02lazybotowl-v-: How could that be wrong?
23:04owl-v-,(print owl-v-)
23:04clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: owl-v- in this context, compiling:(NO_SOURCE_PATH:0:0)>
23:04justin_smith/<command> is a client binding IIRC - "/nick" would only work if clojurebot were using a client that recognizes that as a command to send a nick message
23:05owl-v-ah...
23:05justin_smithbut he uses a clojure lib with bindings on a lib level to send commands - his stream isn't parsed for commands
23:05justin_smithI think
23:06justin_smithfor a while I used a vi-like client where the used :command
23:07owl-v-,(clojurebot)
23:07clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: clojurebot in this context, compiling:(NO_SOURCE_PATH:0:0)>
23:07owl-v-,(lazybot)
23:07clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: lazybot in this context, compiling:(NO_SOURCE_PATH:0:0)>
23:08owl-v-(inc lazybot)
23:08lazybot⇒ 26
23:08owl-v-(inc lazybot)
23:08lazybot⇒ 27
23:08owl-v-why is it increasing ?
23:09owl-v-(dec lazybot)
23:09lazybot⇒ 26
23:09owl-v-(class lazybot)
23:10TEttinger(inc knowledge)
23:10lazybot⇒ 1
23:10TEttingerinc is increment and is, if you omit the , or & to evaluate, a special call to the bot
23:10justin_smith(inc is just a command, not part of the clojure interpreter
23:11TEttingerbasically (inc blah) is a special thing these bots do, that also can't do real evaluation
23:11justin_smith$karma knowledge
23:11lazybotknowledge has karma 1.
23:11TEttinger(inc (str "T" "Ettinger"))
23:11lazybot⇒ 1
23:11TEttinger$karma TEttinger
23:11lazybotTEttinger has karma 15.
23:11justin_smith$karma (str
23:11lazybot(str has karma 0.
23:12justin_smith$karma (str "T" "Ettinger")
23:12lazybot(str has karma 0.
23:12TEttingerha
23:12justin_smith(inc (str "lorem" "ipsum"))
23:12lazybot⇒ 1
23:13justin_smith(karma (str "lorem" "ipsum"))
23:13justin_smith$karma (str "lorem" "ipsum")
23:13lazybot(str has karma 0.
23:13justin_smith(inc (str)
23:13lazybot⇒ 1
23:13justin_smith$karma (str "lorem" "ipsum")
23:13lazybot(str has karma 1.
23:14justin_smithsilliness
23:17yedianyone have experience with environ?
23:18yediwhenever I access a key from `env` it seems to blow away my .lein-env file (aka replace the contents of the file with an empty map)
23:24rberdeenis the second (:require) form from http://dev.clojure.org/jira/browse/CLJS-721 supposed to work?
23:24rberdeen(:require [baz.woz :as woz :refer [one] :refer-macros [two])
23:26rberdeenah, it's http://dev.clojure.org/jira/browse/CLJS-785
23:28yediregarding environ: degrading to 0.4.0 seemed to fix my problem
23:47yedihow exactly do the cljsbuild ids work?
23:48yediom has different cljs build settings for dev and prod, and it's managed by ids. how would I go about creating an uberjar with the specific set of build settings i want?