2014-04-20
| 00:51 | kenrestivo | does this already exist in something else, some other library? https://www.refheap.com/77773 |
| 01:13 | oinksoft | In 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:13 | oinksoft | where you have some constant values that can refer to each other |
| 01:16 | beamso | why wouldn't you just use INFO instead of DEBUG + 1? |
| 01:16 | kenrestivo | oinksoft: 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:17 | beamso | i haven't seen anyone do that sort of enum math in java |
| 01:18 | kenrestivo | otherwise you could hack something like (def loglevels {:debug 1, :info 2, :warning 3}), and (set-loglevel (inc (:debug loglevels)) |
| 01:22 | kenrestivo | i'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:31 | hiredman | in clojure enum type things are typically not numbers, but keywords, so no math |
| 02:07 | oinksoft | hiredman: hm ok |
| 02:07 | oinksoft | hiredman: well the math part (comparison) can be useful: http://www.bpaste.net/show/Jh105vI7FoTM77sl5iAN/ |
| 02:07 | oinksoft | hiredman: pardon the poorly written macro? this is my first one so i don't know the idioms 100% |
| 02:07 | oinksoft | kenrestivo: hm ok, this is the sort of use case i was thinking of (that paste) |
| 02:08 | TEttinger | oinksoft: ##(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:08 | lazybot | ⇒ :info |
| 02:08 | TEttinger | oinksoft: ##(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:08 | lazybot | ⇒ :not-found |
| 02:09 | TEttinger | some fun tricks there, interleave is a useful function for generating hashmaps |
| 02:09 | oinksoft | TEttinger: i see that there are many fun tricks in there... |
| 02:10 | TEttinger | heh, it would be clearer split up |
| 02:10 | oinksoft | ;) |
| 02:10 | TEttinger | but it fits in one IRC message so there |
| 02:10 | oinksoft | but you can compare levels w/ that? |
| 02:10 | TEttinger | yes |
| 02:11 | oinksoft | what does that look like? |
| 02:11 | TEttinger | access-log with one arg, like :debug , produces an int or :not-found |
| 02:11 | TEttinger | starting at 0, going to the max index in the vector log-level |
| 02:11 | TEttinger | I am absolutely certain this can be done better by a more experienced clojurer |
| 02:12 | TEttinger | in particular I bet macros could help, but I haven't touched them |
| 02:12 | TEttinger | (there's probably some way I'm not seeing yet) |
| 02:13 | oinksoft | i see, you have just constructed a reverse lookup |
| 02:14 | oinksoft | thanks TEttinger, that's nice and simple |
| 02:14 | oinksoft | although i do like my enum macro ;) |
| 02:17 | guns | FTR, it's nice to have things like (def FATAL 0) as actual source code |
| 02:18 | oinksoft | you speak for the record? |
| 02:19 | guns | this chat room is logged, so yes :) |
| 02:19 | oinksoft | :) |
| 02:19 | oinksoft | i guess the nice thing in C is you get the type too |
| 02:19 | oinksoft | when you use an enum |
| 02:20 | guns | well, you can ^:const simple Clojure values |
| 02:20 | guns | and you can use core.typed or schema for the typing |
| 02:20 | oinksoft | and you could wrap thatall up in an enum macro ;) |
| 02:20 | guns | (or a simple ^long I suppose) |
| 02:20 | oinksoft | i'll look at core.typed and schema |
| 02:20 | guns | haha yes. Although I had my fill of that kind of thing in ruby |
| 02:21 | guns | cancer of the semicolon, as they say |
| 02:21 | oinksoft | hehe |
| 02:22 | oinksoft | well 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:22 | oinksoft | working in ruby for years i had the same conclusion as you |
| 02:23 | oinksoft | but i feel some pressure to add lots of syntax to clojure programs? do you notice this guns ? |
| 02:23 | oinksoft | *syntactical sugar |
| 02:23 | guns | I think the idea behind the community's love for abstraction is building things around protocols, etc |
| 02:23 | guns | so, no |
| 02:23 | guns | I think it's actually the opposite! |
| 02:23 | oinksoft | maybe this is just the tone of instructional books |
| 02:23 | oinksoft | i am reading two from manning press |
| 02:23 | oinksoft | it reminded me of the ruby community, was turning me off tbh |
| 02:24 | guns | There are differing opinions, but those of us who suffered through Rails projects favor being explicit |
| 02:25 | guns | I 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:25 | Platz | I thought the protocol stuff was for perf gains in the jvm toon |
| 02:25 | oinksoft | for 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:25 | guns | Platz: that too; but it gives you 80% of what you want from polymorphic code |
| 02:25 | oinksoft | but yes, indirection = soul of computer science or something |
| 02:26 | guns | oinksoft: lol; I stepped through a rails app once and found myself ~16 super calls deep |
| 02:26 | guns | maybe it was worse |
| 02:26 | oinksoft | better to forget :) |
| 02:27 | guns | I'd say the Clojure catchphrase is "it's all data" |
| 02:27 | Platz | dare i say tiny polymorphic assemblages lead to category theory |
| 02:28 | guns | how is that? Clojure's protocols don't feel like a "kind-of" relationship |
| 02:29 | guns | not allowing inheritance helps alot |
| 02:30 | arrdem | guns: just because it's not supported doesn't mean people don't use it.. |
| 02:30 | arrdem | guns: and we do have hierarchies which are entirely inheritance based.. |
| 02:31 | guns | arrdem: that's true; I'm just saying extending protocols isn't a feature |
| 02:31 | guns | using the existing Java class hierarchy is quite nice because it's nicely designed |
| 02:33 | arrdem | eh... 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:33 | arrdem | so they're still very much a client driven extension mechanism |
| 02:33 | arrdem | abet in a much more static manner than say multimethods |
| 02:35 | guns | I'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:36 | arrdem | oh totally |
| 02:37 | arrdem | it'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:37 | oinksoft | would it be weird to do (def some-fn (let [stuff (atom {})] (fn ...))) ? or is this common? |
| 02:37 | arrdem | and I think that the focus on the data rather than the structure of the manipulating fns makes it much more flexible and powerfull. |
| 02:37 | oinksoft | for enclosing somethig in that function |
| 02:38 | oinksoft | i usually see `stuff' defined at the same level as `some-fn', not local to `some-fn' |
| 02:38 | arrdem | oinksoft: so I'm not sure you can do exactly that.. |
| 02:38 | guns | oinksoft: mutable global state. have fun! |
| 02:38 | arrdem | oinksoft: but yes you can have lets enclosing defs |
| 02:38 | arrdem | guns: there are legitimate uses for that... memoization caches for instance |
| 02:38 | oinksoft | guns: sorry, stupi dexample w/ the atom |
| 02:38 | oinksoft | guns: i mean more like constants onl important for that function |
| 02:39 | arrdem | oinksoft: it'd be very strange to encapsulate them like that |
| 02:39 | arrdem | oinksoft: if you have some mutable state like an atom... that's almost. almost. ok. |
| 02:39 | arrdem | oinksoft: anything else that's constant and that you may ever want to see somewhere else.. |
| 02:39 | arrdem | oinksoft: not kewl brah |
| 02:40 | oinksoft | hm ok, i felt like maybe this would make for more concise definitions, shorter constant names |
| 02:40 | oinksoft | if it is not idiomatic then ok! |
| 02:41 | guns | global 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:41 | oinksoft | hm i am very uncomfortable w/ using global state |
| 02:42 | oinksoft | erlang makes it much harder to use global state |
| 02:42 | guns | global constant data is great; my knee jerked because you were using an atom |
| 02:42 | oinksoft | *mutable state |
| 02:42 | arrdem | guns: 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:42 | arrdem | guns: some times you do need mutable state |
| 02:43 | arrdem | and that's fine, but usually you can get away with parameterizing everything on a single mutable parameter |
| 02:43 | arrdem | which escapes this "big mutable global singleton" antipattern |
| 02:43 | arrdem | and handles much more nicely in a threaded environment :D |
| 02:43 | guns | arrdem: I have no quarrel with mutable state; there's no getting around it for high performance work for instance |
| 02:44 | arrdem | guns: 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:44 | oinksoft | how do you like to structure your param lists? i do (action/description-args..., subjects) |
| 02:44 | oinksoft | but some people like to put the subjects first |
| 02:45 | arrdem | oinksoft: typically you'll put the highest variance argument first. |
| 02:45 | oinksoft | ah that explains why this works |
| 02:45 | arrdem | oinksoft: 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:46 | arrdem | oinksoft: as-> exists because that isn't always possible... same with ->> |
| 02:46 | oinksoft | hehe sometimes i htink i am overusing -> :) |
| 02:46 | arrdem | no such thing :D |
| 02:47 | guns | There's also the convention of seqable things at the end: (->> [] (map pred …) (remove pred …) …) |
| 02:48 | guns | *sequential things |
| 02:48 | arrdem | guns: this is a good case in point... |
| 02:48 | arrdem | guns: https://github.com/markmandel/brute/blob/master/src/brute/entity.clj#L5 |
| 02:49 | arrdem | guns: having a global mutable def is flat out wrong. |
| 02:49 | arrdem | guns: see the thread... https://github.com/markmandel/brute/issues/1#issuecomment-40435084 |
| 02:50 | guns | yes, totally agree. I've been using stuart sierra's component library with great success |
| 02:50 | arrdem | heh yeah Stuart's reloaded model takes this to the extreme :P |
| 02:51 | guns | arranging components together with async channels is making typical software construction really obvious |
| 02:52 | guns | then prismatic came around and delivered 70% of what I want from a type system |
| 02:52 | arrdem | guns: which lib.. schema? |
| 02:52 | guns | it's been hard to drift away from Clojure with all this great stuff |
| 02:52 | guns | arrdem: yes |
| 02:53 | oinksoft | clojure reminds me of perl in many ways |
| 02:53 | guns | I can see that … at a meta level |
| 02:54 | oinksoft | there is a strong emphasis on practicality over simplicity |
| 02:54 | guns | hmm? |
| 02:54 | guns | those are synonyms |
| 02:57 | oinksoft | guns: ##(count (ns-publics 'clojure.core)) |
| 02:57 | lazybot | java.lang.SecurityException: You tripped the alarm! ns-publics is bad! |
| 02:57 | oinksoft | ah what do i know, but it's 591 here |
| 02:58 | guns | that's the whole "100s of functions on a single data structure|abstraction" perlis quote |
| 02:58 | oinksoft | and lots of convenient syntax over simple syntax |
| 02:59 | guns | oinksoft: I'm not sure I follow that; the syntax is quite convenient, but it's also simple |
| 02:59 | Platz | elepnant in the room is macros |
| 03:00 | guns | clojure.core stays pretty tasteful IMO |
| 03:00 | AmandaC | Platz: no, it’s an elephant. Stop calling it something else, you’re hurting it’s feelings. |
| 03:01 | Platz | what happens when trying new keyboards |
| 03:02 | oinksoft | Platz: yes, tha'ts another thing in clojure that reminds me of perl |
| 03:02 | oinksoft | Platz: perl is a very strong language for writing DSLs |
| 03:03 | AmandaC | Amanda angry! Amanda… too tired to smash, maybe take a nap instead |
| 03:04 | AmandaC | Sorry, I’m a bit loopy on sleep deprevation |
| 03:06 | guns | Perl hackers have stronger stomachs than Clojurists though |
| 03:06 | guns | magic thlobals for instance |
| 03:08 | Platz | perl makes me think of 2600 and phrack |
| 05:54 | ptcek | very 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:00 | katratxo | ptcek: try http://clojure.github.io/clojure/clojure.java.io-api.html#clojure.java.io/reader |
| 07:40 | luxbock | hello, 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:40 | luxbock | I myself have no experience with C++ |
| 07:40 | luxbock | I'm aware of https://github.com/ztellman/gloss and https://github.com/ztellman/vertigo |
| 07:41 | luxbock | they talk about doing interop with C structs/libraries |
| 07:41 | luxbock | would these work just as well for C++, or are there some gotchas I should be aware of? |
| 07:50 | luxbock | someone telling me that doing this is not a good idea would be good advice as well :) |
| 09:10 | gfredericks | technomancy: AND ALSO |
| 09:11 | gfredericks | technomancy: 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:06 | owl-v- | mm~ another day of clojure :-) |
| 10:11 | owl-v- | rrfrfgrfggefddfwsssssqsaqswqqwwwww2qq````````````11````111 |
| 10:11 | owl-v- | ops |
| 13:15 | kras | Hi folks! Is there an equivalent of consp in clojure? |
| 13:15 | kras | Like say cons? |
| 13:16 | kras | I am trying to test if something is a seq? or vector? |
| 13:16 | kras | I can always use an or here |
| 13:16 | kras | just wondering is there is something else |
| 13:16 | bbloom | ~colls |
| 13:16 | clojurebot | colls is seqs and colls |
| 13:16 | bbloom | ~seqs |
| 13:16 | clojurebot | seqs is http://www.brainonfire.net/files/seqs-and-colls/main.html |
| 13:17 | bbloom | kras: that page should reveal all |
| 13:17 | nDuff | kras, 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:18 | kras | just want to know if it is seq? or vector? |
| 13:19 | llasram | What are you actually trying to do with that information? |
| 13:20 | kras | sequential? seems to be serving my purpose |
| 13:20 | kras | thanks for the link bbloom |
| 13:21 | kras | i am trying to flatten a given sequential just as an exercise |
| 13:21 | kras | so had to first check for this |
| 13:22 | bbloom | kras: 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:23 | kras | bbloom: thanks I will keep that in mind |
| 13:24 | kras | I have come up with my own version of flatten wihtout recur ofcourse |
| 13:24 | kras | please comment, appreciate your inputs |
| 13:25 | kras | https://www.refheap.com/77988 |
| 13:26 | kras | this is the first version |
| 13:26 | kras | is it possible to use recur at all for flatten? |
| 13:27 | bbloom | kras: 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:28 | bbloom | kras: your implementation is eager as well. you should try an eager version that does not use reverse (hint: vector + conj) |
| 13:28 | bbloom | kras: after that, try a lazy version using lazy-seq |
| 13:29 | kras | bbloom: when you say eager does that mean fully realizing a seq? |
| 13:30 | bbloom | ,(take 5 (flatten (range))) |
| 13:30 | clojurebot | (0 1 2 3 4) |
| 13:30 | bbloom | kras: that takes 5 items from the result of flattening an infinite sequence |
| 13:30 | bbloom | kras: your code can't do that b/c it tries to walk the entire seq |
| 13:31 | kras | bbloom: oh ok, got it. |
| 13:31 | kras | I will give it a shot |
| 13:31 | bbloom | there are reasons you may want an eager flatten, but generally clojure code prefers to keep seqs lazy until the end: |
| 13:31 | bbloom | ,(into [] (take 5 (flatten (range)))) |
| 13:31 | clojurebot | [0 1 2 3 4] |
| 13:31 | bbloom | the into [] makes it eager |
| 13:31 | bbloom | but the internal laziness of the function pipeline is maintained |
| 13:31 | kras | eager eval should be defintely faster if I am correct? |
| 13:32 | bbloom | kras: it can be, but clojure implements some lazy optimizations such as chunking, etc |
| 13:32 | mpenet | luxbock: 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:32 | mpenet | luxbock: it is gross, but it is fast |
| 13:35 | mpenet | I 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:39 | Jaood | bbloom: do you still love rails? ;) |
| 13:39 | bbloom | Jaood: for what it's good at: absolutely |
| 13:39 | Jaood | came across this: http://www.brandonbloom.name/blog/2011/09/24/one-year-after-accidentally-falling-in-love-with-rails/ |
| 13:39 | bbloom | Jaood: if you've got to make a crud app in a hurry, there is no substitute |
| 13:40 | Jaood | bbloom: but you don't miss ruby right? :) |
| 13:41 | bbloom | Jaood: i much prefer clojure, if that's what you're asking :-P |
| 13:43 | Jaood | bbloom: looks like rails is highly praised for that, gettting crud done quick and safe |
| 13:46 | kras | bbloom: a slightly improved version eliminating reverse |
| 13:46 | kras | will thing about lazy seq |
| 13:47 | kras | think* |
| 13:47 | kras | https://www.refheap.com/77991 |
| 13:49 | bbloom | (doc empty?) ; kras: note the seq idiom |
| 13:49 | clojurebot | "([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:50 | bbloom | kras: 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:50 | kras | ,(= () nil) |
| 13:50 | clojurebot | false |
| 13:51 | bbloom | ,(boolean nil) |
| 13:51 | clojurebot | false |
| 13:51 | bbloom | ,(boolean ()) |
| 13:51 | clojurebot | true |
| 13:51 | bbloom | ,(seq []) |
| 13:51 | clojurebot | nil |
| 13:51 | bbloom | ,(rest [1]) |
| 13:51 | clojurebot | () |
| 13:51 | bbloom | ,(next [1]) |
| 13:51 | clojurebot | nil |
| 13:53 | kras | bbloom: I realize that empty () or [] is not false like in other languages |
| 13:53 | kras | but what is the problem with (= () lis) |
| 13:54 | kras | sorry confused a litle bit |
| 13:54 | llasram | ,(= '() (range)) |
| 13:54 | clojurebot | false |
| 13:56 | bbloom | kras: try (flt nil []) |
| 13:56 | amalloy | kras: 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:56 | llasram | kras: 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:57 | bbloom | kras: instead of (= () lst), try (nil? (seq lis)) |
| 13:58 | bbloom | kras: which is the same as (not (seq lis)) which is empty? |
| 13:58 | amalloy | bbloom: i assume there's some contextual reason i'm missing why (nil? (seq xs)) makes sense over (empty? xs) here? |
| 13:58 | bbloom | amalloy: just for illustrative purposes |
| 14:00 | kras | bbloom: got your point (flt nil []) gives the correct result now |
| 14:00 | kras | will probably take some time to digest this info |
| 14:02 | kras | amalloy: could you please elaborate on what you mean by consing over the result of recursion |
| 14:02 | kras | sorry noob here |
| 14:02 | amalloy | kras: like (cons x (flt ...)) |
| 14:02 | amalloy | rather than (flt ... (conj acc x)) |
| 14:02 | kras | amalloy: oh ok, I agree, |
| 14:03 | kras | I started out trying tail recusion first |
| 14:03 | kras | then realizes this is not possible |
| 14:03 | amalloy | sensible |
| 14:03 | kras | but that acc remianed there |
| 14:04 | kras | thanks a lot guys, that was really insightful discussion |
| 14:04 | kras | will ponder over this for the day |
| 14:05 | kras | time to go bed, have a nice day |
| 14:06 | bbloom | that's not a long day of pondering :-P |
| 14:06 | kras | :-) or should I say for the next day |
| 14:07 | kras | this 4clojure is very addictive i say |
| 14:07 | kras | did not realize it was so late |
| 14:12 | boyscared | might as well just keep going |
| 14:27 | akazlou | hi, 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 | `szx | isn't count O(n)? |
| 14:30 | `szx | ,(doc count) |
| 14:30 | clojurebot | "([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 | `szx | thought i read that somewhere |
| 14:32 | akazlou | 'szx you might right, actually maybe (next seq) is cheaper than count |
| 14:32 | akazlou | might be |
| 14:32 | akazlou | then it would make sense to do |
| 14:32 | `szx | http://stackoverflow.com/a/1273848/318603 |
| 14:34 | `szx | akazlou: yeah, i'm sure there's a good reason though i can't say for sure i know what it is |
| 14:36 | akazlou | ,(map #(instance? clojure.lang.Counted %1) [[] '() {} (seq [])] |
| 14:36 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 14:36 | akazlou | ,(map #(instance? clojure.lang.Counted %1) [[] '() {} (seq [])]) |
| 14:36 | clojurebot | (true true true false) |
| 14:37 | akazlou | so map, vector and list implements Counted, but seq not |
| 14:38 | akazlou | my bad |
| 14:38 | akazlou | (map #(instance? clojure.lang.Counted %1) [[] '() {} (seq [])] |
| 14:38 | akazlou | ,(map #(instance? clojure.lang.Counted %1) [[] '() {} (seq [1])] |
| 14:38 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 14:38 | akazlou | ,(map #(instance? clojure.lang.Counted %1) [[] '() {} (seq [1])]) |
| 14:38 | clojurebot | (true true true true) |
| 14:39 | akazlou | all of them true, just seq on empty list is nil |
| 14:39 | `szx | interesting |
| 14:39 | akazlou | so, count is O(1) for all of them in that case? |
| 14:39 | llasram | akazlou: NB that `seq` on a vector is a special case |
| 14:39 | llasram | ,(type (seq [1])) |
| 14:39 | clojurebot | clojure.lang.PersistentVector$ChunkedSeq |
| 14:40 | llasram | ,(.count (seq [1])) |
| 14:40 | clojurebot | 1 |
| 14:42 | dbasch | I just wrote a few Bitcoin base58 encoding/decoding functions, maybe I should put them on github. Anyone care to review them? |
| 14:42 | dbasch | https://www.refheap.com/77995 |
| 14:43 | akazlou | @llasram, thank you for mentioning this |
| 14:55 | amalloy | llasram: in what way is seq'ing a vector a special case? |
| 14:58 | llasram | amalloy: The `seq` of a vector is `counted?`, but seqs in general are not necessarily |
| 15:01 | amalloy | mmmm. 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:03 | amalloy | seq on a map is counted too, and same for a list (ha ha). and you can make arbitrary instances of Counted yourself |
| 15:03 | llasram | That'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:04 | llasram | But that isn't a guaranteed property of seqs |
| 15:18 | gfredericks | okay so I think I'm going to try to write a multiplexing nrepl middleware |
| 15:19 | gfredericks | Q: should I call it muxrepl or mrepl or something else? |
| 15:20 | whilo | i 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:20 | llasram | gfredericks: What's it going to multiplex? |
| 15:21 | hiredman | gfredericks: manifold |
| 15:21 | llasram | whilo: Are you not getting the full traces in your *nrepl-server* buffer? |
| 15:21 | whilo | nope |
| 15:21 | llasram | Hmm. Odd |
| 15:21 | whilo | just the error message |
| 15:22 | whilo | like: #<NullPointerException java.lang.NullPointerException> |
| 15:22 | llasram | Weird. That looks like something is just `pr`ing the exception object |
| 15:22 | gfredericks | llasram: sessions |
| 15:23 | gfredericks | llasram: biggest immediate win: backgrounding a long-running expression while it's running |
| 15:23 | whilo | llasram: yes |
| 15:23 | gfredericks | llasram: but I also want to use it for implementing a debug-repl |
| 15:24 | akazlou | there is (counted?) in clojure |
| 15:24 | akazlou | ,(doc counted?) |
| 15:24 | clojurebot | "([coll]); Returns true if coll implements count in constant time" |
| 15:24 | llasram | whilo: Wheeeelp. That's not normal. Hmm. This is tricky :-) |
| 15:24 | llasram | gfredericks: I've already got a solution for that -- (def *result (future ...)) ;-) |
| 15:25 | llasram | gfredericks: Oh, so when the debugger gets invoked, it starts another session...? |
| 15:25 | gfredericks | hiredman: is that a ztellman joke? |
| 15:26 | hiredman | gfredericks: no, does he already have a library called manifold? |
| 15:26 | gfredericks | llasram: A) this is for _after_ the fact |
| 15:26 | whilo | some exceptions get thrown properly with stacktraces, so i assume it is core.async specific. not sure though |
| 15:26 | gfredericks | hiredman: yeah |
| 15:26 | hiredman | oh, well, not that then |
| 15:26 | gfredericks | llasram: and yeah, the debug-repl starts another session which you can switch back and forth from |
| 15:26 | gfredericks | hiredman: I didn't know that though, and liked the idea |
| 15:26 | llasram | gfredericks: Neat |
| 15:26 | dbasch | whilo:it’s probably this: https://github.com/clojure/core.async/blob/76b25bf91c670b0c3542ed9cb687ff29fb2183a7/src/main/clojure/clojure/core/async/impl/exec/threadpool.clj#L33 |
| 15:26 | gfredericks | llasram: I already have something better than futures actually, but it still requires forethought |
| 15:27 | whilo | dbasch: very well, thx |
| 15:27 | whilo | why is it println'ed? is there a idiomatic way to tune that? |
| 15:28 | llasram | whilo, dbasch: Ouch. That's not very friendly |
| 15:29 | whilo | i 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:29 | hiredman | gfredericks: how about manigfeald, which is, according to google, the old english word manifold comes from |
| 15:29 | hiredman | lots of google juice, no idea how to pronounce it |
| 15:29 | gfredericks | hiredman: ha |
| 15:29 | dbasch | whilo: ask Rich Hickey, or file an issue / pull request |
| 15:29 | llasram | Not a pull request |
| 15:30 | llasram | But yeah, check to see if there's an issue already on the core.async JIRA |
| 15:30 | whilo | ok. people seem to be programming fault free, when i am the first to have a problem with this XD |
| 15:30 | llasram | That seems like the worst possible behavior for it, short of silently swallowing the exception |
| 15:30 | hiredman | whilo: the first thing to do is to see if it is repropducible outside of lein repl, cider, or whatever tools |
| 15:31 | whilo | lein test reproduces it as well |
| 15:31 | whilo | or lein run |
| 15:32 | llasram | hiredman: The linked core.async code just calls `println` on any exceptions thrown from async tasks |
| 15:32 | llasram | So no possibility of stacktraces ever |
| 15:32 | hiredman | ah |
| 15:32 | hiredman | well, what should it do? |
| 15:32 | llasram | Print a stack trace? |
| 15:32 | hiredman | to where? |
| 15:33 | llasram | Anywhere :-) I mean, right now it unilaterally prints something useless to *out* |
| 15:33 | llasram | It seems like an incremental improvement would be to print something useful to *out* |
| 15:33 | llasram | Then go from there |
| 15:34 | hiredman | llasram: 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:34 | whilo | printing stacktrace fixes my issue :-) |
| 15:35 | whilo | hiredman: that didn't work for me |
| 15:35 | whilo | hiredman: weren't they outside this try-catch block? |
| 15:35 | dbasch | hiredman: see the code: https://github.com/clojure/core.async/blob/76b25bf91c670b0c3542ed9cb687ff29fb2183a7/src/main/clojure/clojure/core/async/impl/exec/threadpool.clj#L33 |
| 15:35 | whilo | much better, now i only feel half blind :-) |
| 15:36 | hiredman | dbasch: I see it |
| 15:36 | dbasch | no question that printing a stacktrace would be better than .toString |
| 15:36 | hiredman | dbasch: but what if I don't want to print the stacktrace |
| 15:37 | dbasch | hiredman: what if you don’t want to print .toString? |
| 15:37 | dbasch | same thing |
| 15:37 | hiredman | whilo: I doubt that, my guess would be you put the try/catch in the wrong place then |
| 15:37 | dbasch | but if you choose one, stacktrace is a more useful default |
| 15:37 | hiredman | dbasch: sure, I would argue it should do neither |
| 15:37 | hiredman | dbasch: it looks like the commit that introduced that left debugging printlns in a number of places :/ |
| 15:38 | llasram | hiredman: Ohhhh, maybe that's what they are. I just noticed that |
| 15:38 | llasram | There's also this issue http://dev.clojure.org/jira/browse/ASYNC-61 which seems to reflect the behavior prior to that commit |
| 15:40 | hiredman | the 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:41 | dbasch | the comment at the end is right, it seems that the fix was a quick hack |
| 15:41 | llasram | hiredman: Which makes me sad :-/ |
| 15:42 | hiredman | llasram: yep, maybe some day it will settle down, it is still "alpha" |
| 15:42 | llasram | And no tbaldridge ATM to grill about it :-) |
| 15:42 | hiredman | llasram: I am sure he would point to the aplha designator |
| 15:42 | llasram | Probably so |
| 15:43 | dbasch | before coding anything, it would be worth thinking about how logging should work for core.async and then implement that |
| 15:44 | dbasch | logging has been one of the most annoying parts of java since forever |
| 15:44 | whilo | that indeed was interesting to me as well, as i need to address logging with it soon as well |
| 15:44 | hiredman | clojure.tools.logging words fine |
| 15:44 | hiredman | works |
| 15:44 | llasram | (inc hiredman) |
| 15:44 | lazybot | ⇒ 44 |
| 15:45 | dbasch | hiredman: but core.async doesn’t use it :) |
| 15:45 | hiredman | dbasch: right, logging is your concern as a consumer of core.async |
| 15:46 | hiredman | core.async shouldn't dictate how you do logging |
| 15:48 | llasram | Someone needs to create an SLF4J backend for timbre, then the great cycle of JVM logging will be complete |
| 15:50 | sveri | Hi, 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:53 | ToBeReplaced | llasram: do you use timbre? |
| 15:54 | llasram | ToBeReplaced: Nope. tool.logging |
| 15:54 | ToBeReplaced | llasram: yeah, same... wondering why someone would use it instead |
| 15:55 | llasram | ToBeReplaced: JVM logging is complex enough -- I don't see how adding an entirely new language-specific logging library makes it better |
| 15:56 | llasram | I've heard people say they couldn't get tools.logging + <Java logging library> configured properly, while timbre is apparently much easier to setup |
| 15:56 | llasram | And also cite the lack of XML |
| 15:57 | llasram | OTOH, I just use slfj+log4j w/ the same short ->stderr property file everywhere, so YMMV |
| 15:58 | ToBeReplaced | llasram: 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:59 | ToBeReplaced | llasram: 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:59 | ToBeReplaced | banned* |
| 15:59 | llasram | I don't think timbre is ClojureWerkz. Just "supports their goals" |
| 16:00 | hiredman | friend of my enemy, etc |
| 16:00 | ToBeReplaced | i got bannedd from a taoensso library, heh |
| 16:00 | llasram | Ahh |
| 16:00 | llasram | I was just thinking the Clojure community needed some more drama |
| 16:00 | llasram | Liven things up a bit |
| 16:01 | hiredman | do I want to use a library with goals? what if it doesn't match my lifestyle? |
| 16:02 | llasram | What if you grow apart over time, and realize some day that you want to structure your APIs entirely differently? |
| 16:03 | hiredman | what if I "link" against the api, but I am not "linking" against the api? |
| 16:04 | llasram | You can try spicing things up with a compatibility shim! |
| 16:05 | ToBeReplaced | i 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:05 | ToBeReplaced | if either of you (or onlookers) have a similar list i'd be interested in seeing it |
| 16:08 | llasram | Hmm, interesting. There's definitely some de facto standard stuff I use everywhere (ring, cheshire), but yeah -- not a lot |
| 16:09 | whodidthis | how do i convert these javascript object properties, kind of like arrays, into vectors http://pastebin.com/vdqxdGZx |
| 16:11 | llasram | ToBeReplaced: I'm going to chalk it up to the Lisp curse :-) |
| 16:12 | ToBeReplaced | llasram: 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:12 | amalloy | what does it even mean to be banned from a repo, ToBeReplaced? |
| 16:13 | ToBeReplaced | as basic example -- distinguishing between 405 and 404 using a clojure routing solution seems to be tricky |
| 16:13 | llasram | ToBeReplaced: 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:13 | ToBeReplaced | amalloy: when i try to post comments in issues i get informed i've been blocked from the repository |
| 16:13 | amalloy | huh. i didn't even know that was possible |
| 16:14 | amalloy | brb gonna ban some folks from my repos, for science |
| 16:14 | llasram | SWEET |
| 16:14 | verma | when 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:14 | dbasch | whodidthis: https://github.com/clojure/clojurescript/blob/master/src/cljs/cljs/core.cljs#L7356 |
| 16:15 | ToBeReplaced | verma: consider using JVM options and accessing via System/getProperty |
| 16:15 | amalloy | huh. i can't find that option. i wonder if they asked github support specially |
| 16:15 | llasram | verma: Alternatively, consider passing in different arguments the function constructing your handler chain for "dev" vs "production" |
| 16:16 | llasram | My experience is that trying to have stuff which automatically acts differently based on different "environments" creates a lot of hassle |
| 16:16 | llasram | Especially e.g. around running "test" tests within your "dev" REPL |
| 16:18 | ToBeReplaced | amalloy: https://help.github.com/articles/blocking-a-user |
| 16:18 | verma | ToBeReplaced, llasram, got it, thanks :) |
| 16:18 | coventry` | verma: You might find carica useful for distinguishing dev from production. Environment variables and System/getenv work too. |
| 16:19 | llasram | Stops them from forking? Wow |
| 16:19 | amalloy | llasram: well, with a fork of a repo you can make yourself a bit of a nuisance |
| 16:19 | llasram | How so? |
| 16:19 | verma | coventry`, thanks, I think I will go the system env route I think |
| 16:19 | amalloy | eg, commit a hundred things that say: "Fixes #121. Repo owner is a nazi." |
| 16:20 | amalloy | those show up in the discussion thread of #121 in the base repo |
| 16:20 | llasram | Oh, geez. I didn't realize that |
| 16:20 | ToBeReplaced | verma: 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:20 | amalloy | but 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:20 | llasram | Sure |
| 16:21 | whodidthis | dbasch: returns the object :( maybe ill figure out something else |
| 16:21 | llasram | Oh, humans |
| 16:36 | verma | ToBeReplaced, hmmm, sounds good, taking a look |
| 16:37 | verma | ToBeReplaced, 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:39 | justin_smith | you can't specify jvm opts in a jar, it simply doesn't work that way |
| 16:40 | verma | justin_smith, yeah I know, what I meant was that they will be absent |
| 16:40 | justin_smith | I wasn't sure if you were being sarcastic |
| 16:41 | verma | :) |
| 16:41 | `szx | with 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 | `szx | i guess #datomic would be a better place to ask |
| 16:42 | `szx | heh |
| 16:42 | verma | justing_smith, don't think I was being sarcastic, may be not a very coherent thought on my part :) |
| 17:02 | DomKM | Is there a protocol for clojure.core/contains? |
| 17:04 | amalloy | DomKM: an interface |
| 17:04 | amalloy | should be clojure.lang.ILookup iirc |
| 17:04 | DomKM | thanks amalloy |
| 17:09 | Krajsnick | Could 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:09 | Krajsnick | How can the Clojure fib function be so fast? |
| 17:09 | ivan | fibonacci can be computed sequentially |
| 17:10 | justin_smith | yeah, it's probably using the memoizing algorithm |
| 17:10 | Krajsnick | one of the ones I tried used a memoizing function yes |
| 17:11 | Krajsnick | So 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:12 | justin_smith | do you have links to the various implementations? |
| 17:12 | Krajsnick | sure |
| 17:12 | Krajsnick | http://stackoverflow.com/questions/8939970/a-recursive-fibonacci-function-in-clojure |
| 17:12 | Krajsnick | I used a couple of these |
| 17:12 | Krajsnick | all of them gives me answer instantly |
| 17:13 | Krajsnick | now I found one that doesn't, and was 2-3 seconds slower than node |
| 17:13 | Krajsnick | http://intothewebs.tumblr.com/post/45073028163/a-little-bit-of-clojure the first fib function |
| 17:20 | justin_smith | yeah, that one is not memoizing, and also not tail recursive |
| 17:25 | perses | is there anybody using titanum graph lib? |
| 17:41 | justin_smith | perses: I've been meaning to try it out |
| 17:42 | DomKM | amalloy: How would you create a type that implements clojure.core/contains? It looks like ILookup is for clojure.core/get |
| 17:42 | justin_smith | DomKM: I think if you implement ILookup you get bot get and contains? |
| 17:43 | justin_smith | since get also needs to know whether a value is present or not |
| 17:43 | DomKM | java.lang.IllegalArgumentException: contains? not supported on type: |
| 17:43 | DomKM | but get works fine |
| 17:43 | coventry | What'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:43 | justin_smith | DomKM: OH, I don't know then |
| 17:44 | reiddraper | coventry: hmm, is this a pure function? |
| 17:44 | amalloy | yeah, apparently contains? is a bit weird |
| 17:45 | amalloy | you need to implement one of: Associative, IPersistentSet, Set, or Map |
| 17:45 | amalloy | which doesn't seem very nice to me |
| 17:45 | reiddraper | coventry: you can use gen/return to create a 'constantly' generator |
| 17:46 | coventry | reiddraper: 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:46 | reiddraper | coventry: so will that be adding randomness that is not controlled by test.check? |
| 17:46 | reiddraper | coventry: if so, I would recommend against that if possible |
| 17:47 | DomKM | amalloy: Set makes sense for my use case. Do you know the protocol/interface for it? |
| 17:47 | amalloy | i listed the names of all the interfaces just above |
| 17:47 | amalloy | java.util.Set, or clojure.lang.IPersistentSet |
| 17:48 | coventry | reiddraper: That was the idea, though I'm open to suggestions for other ways to construct objects with lots of structural sharing. |
| 17:48 | coventry | Ah, you don't want to add extra randomness because it breaks shrinking, I guess? |
| 17:48 | amalloy | coventry: what about a vector that contains all the objects you want to share, and use like one-of to choose from its items? |
| 17:49 | DomKM | thanks |
| 17:49 | reiddraper | coventry: what's wrong with creating generators the 'normal' way? |
| 17:49 | reiddraper | i'm not sure i follow how structural sharing is relevant here |
| 17:50 | coventry | I want to make tests for an object serializer which is aware of structural sharing. |
| 17:51 | reiddraper | so, if you serialize X, and then later serialize Y, which shares some structure, it has some different behavior than normal serialization would? |
| 17:52 | coventry | reiddraper: No, I want the serialization of [X X X X] to only contain one serialization of X. |
| 17:53 | reiddraper | and right now you verify that across different test runs? Or within a single test? |
| 17:53 | coventry | (This is for cljs, BTW. I imagine there's already an option for this in java.) |
| 17:54 | reiddraper | coventry: from what i've heard so far this wouldn't be easier/harder in clj/cljs |
| 17:54 | coventry | reiddraper: 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:56 | reiddraper | coventry: 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:56 | reiddraper | that way you don't need to use a stateful atom to 'remember' things across test runs |
| 17:57 | coventry | Yes, the shrinking property is worth preserving, thanks for pointing that out. |
| 17:57 | reiddraper | and reproducibility |
| 17:58 | reiddraper | despite being a 'random' testing tool, test.check has provisions for repeating the exact same random test |
| 17:59 | coventry | Hmm, 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:09 | coventry | Can I use gen/bind recursively? |
| 18:10 | reiddraper | coventry: yes, it's quite common to |
| 18:11 | coventry | Great, are there any examples you can easily point me to? |
| 18:16 | coventry | In 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:18 | akhudek | Regarding 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:19 | coventry | akhudek: 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:20 | coventry | akhudek: https://github.com/swannodette/om/blob/master/src/om/core.cljs#L239 |
| 18:25 | perses | justin_smith: still there? |
| 18:25 | justin_smith | yes, hi |
| 18:26 | perses | justin_smith: hi, so you have tried it yet? |
| 18:26 | justin_smith | not really, no - but if you have a problem or question it can't hurt to ask |
| 18:27 | perses | justin_smith: how can i add vertex uniquely to the graph? |
| 18:28 | perses | if i did (tg/transact! (tv/create! {:name "hello"}) (tv/create! {:name "hello"}) (tv/create! {:name "hello"})), will add 3 vertices |
| 18:28 | perses | but the logic is it should be one? |
| 18:28 | justin_smith | titanium.clojurewerkz.org/articles/vertices.html unique-upsert looks like it may be the thing? |
| 18:28 | justin_smith | yeah, you want the unique-upsert! function for that (it meantions it right after create! in the docs I linked) |
| 18:29 | perses | ah so i should replace tv/create! to tv/unique-upsert! ? |
| 18:30 | justin_smith | I think so, but only based on reading the docs just now - it may be more complex than that |
| 18:30 | justin_smith | can't hurt to try |
| 18:30 | justin_smith | oh, upsert needs a location |
| 18:32 | coventry | reiddraper: NM, I see how to do it now. |
| 18:32 | reiddraper | coventry: cool |
| 18:32 | coventry | Thanks for your help. |
| 18:37 | akhudek | coventry: 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:40 | coventry | akhudek: 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:42 | coventry | akhudek: 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:45 | akhudek | each 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:46 | akhudek | coventry: 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:49 | akhudek | coventry: also, calling render doesn’t actually mean that it will update the dom, right? or does it? |
| 18:50 | coventry | akhudek: No, my understanding is that the actual dom element will not be updated unless the output of the render method has changed. |
| 18:53 | coventry | akhudek: 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:54 | akhudek | coventry: yeah, I didn’t think it should be calling render either. |
| 19:16 | coventry | I'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:18 | dbasch | what’s the best / usual way to tell a cljs app that it’s running in production or dev? |
| 19:19 | akhudek | coventry: figured out why it’s calling render at least. The items are = but not identical. |
| 19:20 | coventry | akhudek: Oh, it wasn't just a rearrangement of the list? That makes sense. |
| 19:22 | coventry | dbasch: You can use a macro to do it whatever way you do it in clj, at compile time. |
| 19:27 | akhudek | coventry: oh man, implementing a custom should-update that swaps the identical? check for = completely fixed the performance problems. |
| 19:28 | coventry | akhudek: Yeah, I had a similar experience. |
| 19:30 | akhudek | I’m curious about dnolen_’s thoughts on this. |
| 19:31 | coventry | Well, an equality check is expensive. The whole reason om is more performant than react is that it does identity checks. |
| 19:31 | dbasch | coventry: In clj I use the jvm environment, but I’ll look into carica |
| 19:32 | coventry | dbasch: Not sure why, but wiser people than me were saying earlier that jvm-opts is the way to go. |
| 19:33 | dbasch | coventry: ok, but what do you do in the browser? |
| 19:33 | dnolen_ | akhudek: as a general rule that will slow things down in Om |
| 19:34 | dnolen_ | akhudek: at least in the current version anyway, working on some things that will allow us to switch to = over identical? |
| 19:34 | coventry | dbasch: You make a java macro, which you call at compile time in your clojurescript. |
| 19:34 | dbasch | coventry: you mean a clj macro that reads from the jvm environment, I assume |
| 19:35 | coventry | dbasch: yeah, like (defmacro prod? [] (System/getenv "PROD")) |
| 19:37 | justin_smith | coventry: but that would check whether compilation was happening where PROD is set - it could cause unexpected results with uberjar creation |
| 19:38 | justin_smith | if aot is involved, at least |
| 19:38 | dbasch | coventry: it would be better to do something with the dev/prod profiles in cljsbuild |
| 19:41 | coventry | dbasch: You're right. |
| 19:41 | coventry | justin_smith: I was just giving an example of how to get something from the outside environment into cljs. |
| 19:41 | justin_smith | ahh, ok |
| 19:42 | dbasch | coventry: 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:43 | frustration-stat | I 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:43 | justin_smith | have the app create a file recording its PID and metadata about itself? |
| 19:43 | coventry | dbasch: 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:44 | dbasch | coventry: yes, I cannot think of a better option |
| 19:45 | frustration-stat | ie: (use '[clojure.tools.cli :as cli :only [parse-opts]]) => IllegalAccessError parse-opts does not exist clojure.core/refer (core.clj:3849) |
| 19:45 | frustration-stat | |
| 19:47 | dbasch | frustration-stat: what’s your project.clj? |
| 19:48 | frustration-stat | dbasch: i've tried with [org.clojure/tools.cli "0.3.1"] in project.clj and i've also tried with lein-try |
| 19:48 | frustration-stat | same result |
| 19:48 | akhudek | dnolen_: 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:49 | frustration-stat | dbasch: the only way i've gotten it to work is to clone the github repo and run a lein repl from the checkout |
| 19:49 | dnolen_ | akhudek: sure, IShouldUpdate is there for a reason |
| 19:50 | dnolen_ | akhudek: however it important that you understand the default implementation (or copy and paste it and just change the bit you need) |
| 19:50 | dbasch | frustration-stat: I just created a blank project with clojure 1.5.1 and it works fine |
| 19:50 | dbasch | frustration-stat: what clojure are you using? |
| 19:51 | akhudek | dnolen_: yeah, I’ve copied and modifed the cond here https://github.com/swannodette/om/blob/master/src/om/core.cljs#L239 |
| 19:51 | frustration-stat | dbasch: i'vew tried both 1.5.1 and 1.6.0 |
| 19:51 | dbasch | frustration-stat: (same with 1.6.0) |
| 19:51 | akhudek | dnolen_: 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:51 | dbasch | frustration-stat: there’s probably a dependency conflict, you should post your project.clj or run lein deps :tree |
| 19:52 | coventry | akhudek: How does it break? |
| 19:52 | dnolen_ | 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:52 | dnolen_ | akhudek: care to elaborate on the set cursor? not really following |
| 19:54 | frustration-stat | dbasch: i just tried a blank project, must be a conflict, checking :tree, thanks |
| 19:55 | akhudek | dnolen_: 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:55 | akhudek | hold on and I’ll link the implemenation, it’s just a small modification to mapcursor |
| 19:56 | akhudek | https://github.com/akhudek/om/blob/set-cursor/src/om/core.cljs#L415 |
| 19:56 | akhudek | Also modified to-cursor to be aware of sets. |
| 19:56 | akhudek | other than the state, it seems to work |
| 20:00 | dnolen_ | akhudek: yeah another issue that will be solved by what I'm working on |
| 20:02 | akhudek | dnolen_: ok, sounds good. Is there documentation for the :ctor option you mentioned above? I’m not familiar with it. |
| 20:02 | dnolen_ | akhudek: you can supply an alternative backing React component, an alternative to pure |
| 20:02 | coventry | ,(let [len 1e7 a (doall (range len)) b (doall (range len))] (time (= a b))) |
| 20:02 | clojurebot | #<OutOfMemoryError java.lang.OutOfMemoryError: Java heap space> |
| 20:03 | coventry | ,(let [len 1e5 a (doall (range len)) b (doall (range len))] (time (= a b))) |
| 20:03 | clojurebot | "Elapsed time: 65.673784 msecs"\ntrue |
| 20:03 | coventry | (let [len 1e5 a (range len) b (range len)] (time (= a b))) |
| 20:03 | coventry | ,(let [len 1e5 a (range len) b (range len)] (time (= a b))) |
| 20:03 | clojurebot | "Elapsed time: 68.550158 msecs"\ntrue |
| 20:04 | dnolen_ | akhudek: it's documented in build's docstring but there's not an example yet beyond the `harmful` example in the repo |
| 20:04 | coventry | Why does this equality check take almost the same time whether or not I force the structures with doall before the clock starts? |
| 20:05 | coventry | (With length 1e7 on a real machine, doall only knocks off about 20% of the time) |
| 20:05 | dnolen_ | coventry: ranges aren't lazy seqs |
| 20:05 | akhudek | dnolen_: ok, thanks, I’ll read up on that |
| 20:07 | coventry | ,(class (range 10)) |
| 20:07 | clojurebot | clojure.lang.LazySeq |
| 20:09 | dnolen_ | coventry: oh hmm, perhaps getting confused because there's a Range.java and Range deftype in ClojureScript |
| 20:13 | Bronsa | dnolen_: looks like clojure's range uses chunked buffers |
| 20:13 | dnolen_ | Bronsa: yeah |
| 20:14 | Bronsa | Range.java looks exactly like cljs Range OTOH |
| 20:15 | dnolen_ | Bronsa: yeah chunked buffers came late to ClojureScript |
| 20:15 | coventry | Even with chunking, I would have expected the object creation to be more expensive than the equality check. Am I just wrong about that? |
| 20:58 | amalloy | coventry: 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:00 | coventry | No, 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:09 | amalloy | you need to take care when benchmarking anything. small sample sizes in unrealistic situations don't tell the real story |
| 21:09 | TravisD | I am really not trying to troll. Is there a performance improvement to using scala over clojure? |
| 21:13 | kras | came up with the following code for my own version of flatten https://www.refheap.com/78032 |
| 21:13 | kras | I am trying to make it do lazy eval |
| 21:14 | coventry | amalloy: Thanks, it looks like the answer is "use jsperf.com". Sounds easy... |
| 21:14 | kras | looks like the trail and error method of inserting lazy-seq on recursion calls is not helping |
| 21:14 | kras | any suggestions? |
| 21:15 | coventry | Maybe http://clojuredocs.org/clojure_core/1.2.0/clojure.core/lazy-cat ? |
| 21:16 | jdkealy | I'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:18 | amalloy | yeah, instead of into, just use concat |
| 21:18 | amalloy | and wrap the whole thing in a lazy-seq |
| 21:19 | kras | ,(concat ["a"] ["b"]) |
| 21:19 | clojurebot | ("a" "b") |
| 21:19 | ivan | is there a try/catch/else macro somewhere? |
| 21:19 | kras | amalloy: coventry: thanks for the clue |
| 21:20 | amalloy | ivan: what would the else do? |
| 21:20 | ivan | amalloy: run something if no exception was caught |
| 21:21 | amalloy | that's just...more stuff after the try |
| 21:21 | amalloy | (try (a) (b) (catch)) |
| 21:21 | amalloy | unless you really really don't want to catch them in b, i guess |
| 21:21 | ivan | no, because then the catch covers (b) |
| 21:21 | ivan | right |
| 21:21 | ivan | Python has this :) |
| 21:22 | kras | hurray, (take 5 (flt (range))) works now with stackoverflow :-) |
| 21:23 | kras | I meant without* |
| 21:26 | coventry | I'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:27 | coventry | (Response when I mixed that message to ##javascript: "<j201> THE PARENS THEY BURN") |
| 21:29 | kras | any suggestions on whom to follow on 4clojure's solutions list |
| 21:29 | coventry | daowen is the shit. |
| 21:32 | ivan | I feel like Clojure code could use some vertical whitespace outside of cond |
| 21:33 | kras | coventry: real cool man, he just did it in one line and its more readable |
| 21:33 | kras | thanks for the suggestion |
| 21:33 | justin_smith | ivan: -> / ->> lead to good vertical whitespace |
| 21:34 | ivan | it does? my imagination is failing me |
| 21:34 | justin_smith | wait, I could be misunderstanding you |
| 21:34 | clojurebot | Gabh mo leithscéal? |
| 21:35 | justin_smith | how does cond lead to good vertical whitespace? |
| 21:35 | Frozenlock | coventry: I feel the lack of parens disturbing. It's like driving at high speed without a seat belt. |
| 21:36 | Frozenlock | er.. "the lack of parens is disturbing" |
| 21:36 | ivan | justin_smith: blank lines between things |
| 21:37 | justin_smith | ivan: 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:39 | justin_smith | I have a coworker who pretty much puts empty lines in his defns whereever |
| 21:39 | justin_smith | it kind of breaks how I use emacs though |
| 21:41 | fuJiin | noob question - anybody building webapps use futures for parallel db calls? |
| 21:42 | fuJiin | anything to watch out for when doing this? |
| 21:42 | justin_smith | it may not help much if the parallel calls are to the same db |
| 21:43 | coventry | justin_smith: How does that break emacs? |
| 21:44 | justin_smith | it breaks the "defun is separated by blank lines" assumption used by many of my favorite keybindings |
| 21:44 | kras | how do I know if a function evals lazily? |
| 21:44 | fuJiin | its the same db, but so far its shaved a full second off response times |
| 21:44 | justin_smith | coventry: not "break" really as much as make them not be as useful |
| 21:44 | coventry | Oh, OK. |
| 21:44 | kras | the mapcat function doc doesn't say anything about laziness but looks like it evals lazily |
| 21:45 | justin_smith | kras: the way to check is the type of the output |
| 21:45 | justin_smith | ,(class (mapcat identity (range))) |
| 21:45 | clojurebot | clojure.lang.LazySeq |
| 21:45 | justin_smith | that's how you know |
| 21:46 | kras | justin_smith: thank you |
| 22:17 | kras | I have written my own version of max as https://www.refheap.com/78039 |
| 22:17 | kras | this works fine in my repl |
| 22:17 | kras | but gives an error on 4clojure |
| 22:18 | kras | clojure.lang.ArityException: Wrong number of args (1) passed to: core$partial |
| 22:27 | danlamanna | can anyone tell me why the first works and the second doesn't? https://gist.github.com/danlamanna/11130607 |
| 22:28 | owl-v- | does .isFile returns boolean? |
| 22:29 | `szx | danlamanna: because it's a java method, not a function? |
| 22:29 | `szx | ,(doc memfn) |
| 22:29 | clojurebot | "([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 | `szx | danlamanna: ^ |
| 22:29 | danlamanna | ahh |
| 22:31 | Bronsa | danlamanna: methods are not first-class like functions, you have to wrap method calls in fns if you need to use them as such. |
| 22:31 | owl-v- | (not= (filter (method) (stuff)) (filter (boolean) (stuff)) ) |
| 22:31 | dbasch | danlamanna: you can wrap it like this: #(.isFile %) |
| 22:36 | justin_smith | it 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:38 | justin_smith | but 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:46 | owl-v- | is (defn fun [] (fun)) same as (defn fun [] (recur)) ??? |
| 22:46 | lazybot | owl-v-: How could that be wrong? |
| 22:47 | justin_smith | owl-v-: there is no such thing as implicit tail recursion in clojure |
| 22:47 | justin_smith | so they are not the same |
| 22:47 | justin_smith | *implicit tail recursion optimization |
| 22:49 | owl-v- | (defn fun [] (fun)) < (defn fun [] (recur)) ??? |
| 22:49 | lazybot | owl-v-: How could that be wrong? |
| 22:49 | owl-v- | lol. lazybot~ |
| 22:49 | justin_smith | well the latter is optimized |
| 22:49 | justin_smith | usually you want that |
| 22:52 | owl-v- | justin_smith: thanks |
| 22:53 | bbloom | apparently three question marks is wildly inappropriate conduct, says lazybot ??? |
| 22:53 | lazybot | bbloom: Yes, 100% for sure. |
| 22:53 | bbloom | (inc lazybot) |
| 22:53 | lazybot | ⇒ 25 |
| 22:53 | justin_smith | what about 4 question marks ???? |
| 22:53 | justin_smith | hmm ??? |
| 22:53 | lazybot | justin_smith: Oh, absolutely. |
| 22:54 | bbloom | or an interrobang ‽ |
| 22:54 | owl-v- | what does '???' do ??? |
| 22:54 | lazybot | owl-v-: Oh, absolutely. |
| 22:54 | bbloom | it does stuff ‽‽‽ |
| 22:54 | agarman | ,(apply str (repeat 3 \?))) |
| 22:54 | clojurebot | "???" |
| 22:55 | bbloom | agarman: the bots ignore each other |
| 22:55 | bbloom | ,(println "???") |
| 22:55 | clojurebot | ???\n |
| 22:55 | bbloom | ,(print "???") |
| 22:55 | clojurebot | ??? |
| 22:55 | bbloom | ??? |
| 22:55 | lazybot | bbloom: Yes, 100% for sure. |
| 22:56 | owl-v- | lazybot accepts only user message ??? |
| 22:56 | lazybot | owl-v-: How could that be wrong? |
| 22:58 | schlegel | ??? |
| 22:58 | lazybot | schlegel: Oh, absolutely. |
| 22:58 | schlegel | What's the point |
| 22:58 | owl-v- | ,(prn "yes ???") |
| 22:58 | clojurebot | "yes ???"\n |
| 22:58 | owl-v- | ,(print "yes ???") |
| 22:58 | clojurebot | yes ??? |
| 22:58 | justin_smith | ,'??? |
| 22:59 | clojurebot | ??? |
| 22:59 | lazybot | justin_smith: How could that be wrong? |
| 22:59 | owl-v- | justin_smith: u did it! |
| 22:59 | schlegel | No it replied to him |
| 23:00 | justin_smith | ,(:q '{:q ??? :a !!!}) |
| 23:00 | clojurebot | ??? |
| 23:00 | owl-v- | ,'final boss ??? |
| 23:00 | clojurebot | final |
| 23:00 | lazybot | owl-v-: Oh, absolutely. |
| 23:00 | owl-v- | oh |
| 23:01 | owl-v- | ,(print "/NICK clojurebot2") |
| 23:01 | clojurebot | /NICK clojurebot2 |
| 23:02 | owl-v- | ,(print "???") |
| 23:02 | clojurebot | ??? |
| 23:02 | owl-v- | bot can't change nickname??? |
| 23:02 | lazybot | owl-v-: How could that be wrong? |
| 23:04 | owl-v- | ,(print owl-v-) |
| 23:04 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: owl-v- in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 23:04 | justin_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:05 | owl-v- | ah... |
| 23:05 | justin_smith | but he uses a clojure lib with bindings on a lib level to send commands - his stream isn't parsed for commands |
| 23:05 | justin_smith | I think |
| 23:06 | justin_smith | for a while I used a vi-like client where the used :command |
| 23:07 | owl-v- | ,(clojurebot) |
| 23:07 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: clojurebot in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 23:07 | owl-v- | ,(lazybot) |
| 23:07 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: lazybot in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 23:08 | owl-v- | (inc lazybot) |
| 23:08 | lazybot | ⇒ 26 |
| 23:08 | owl-v- | (inc lazybot) |
| 23:08 | lazybot | ⇒ 27 |
| 23:08 | owl-v- | why is it increasing ? |
| 23:09 | owl-v- | (dec lazybot) |
| 23:09 | lazybot | ⇒ 26 |
| 23:09 | owl-v- | (class lazybot) |
| 23:10 | TEttinger | (inc knowledge) |
| 23:10 | lazybot | ⇒ 1 |
| 23:10 | TEttinger | inc is increment and is, if you omit the , or & to evaluate, a special call to the bot |
| 23:10 | justin_smith | (inc is just a command, not part of the clojure interpreter |
| 23:11 | TEttinger | basically (inc blah) is a special thing these bots do, that also can't do real evaluation |
| 23:11 | justin_smith | $karma knowledge |
| 23:11 | lazybot | knowledge has karma 1. |
| 23:11 | TEttinger | (inc (str "T" "Ettinger")) |
| 23:11 | lazybot | ⇒ 1 |
| 23:11 | TEttinger | $karma TEttinger |
| 23:11 | lazybot | TEttinger has karma 15. |
| 23:11 | justin_smith | $karma (str |
| 23:11 | lazybot | (str has karma 0. |
| 23:12 | justin_smith | $karma (str "T" "Ettinger") |
| 23:12 | lazybot | (str has karma 0. |
| 23:12 | TEttinger | ha |
| 23:12 | justin_smith | (inc (str "lorem" "ipsum")) |
| 23:12 | lazybot | ⇒ 1 |
| 23:13 | justin_smith | (karma (str "lorem" "ipsum")) |
| 23:13 | justin_smith | $karma (str "lorem" "ipsum") |
| 23:13 | lazybot | (str has karma 0. |
| 23:13 | justin_smith | (inc (str) |
| 23:13 | lazybot | ⇒ 1 |
| 23:13 | justin_smith | $karma (str "lorem" "ipsum") |
| 23:13 | lazybot | (str has karma 1. |
| 23:14 | justin_smith | silliness |
| 23:17 | yedi | anyone have experience with environ? |
| 23:18 | yedi | whenever 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:24 | rberdeen | is the second (:require) form from http://dev.clojure.org/jira/browse/CLJS-721 supposed to work? |
| 23:24 | rberdeen | (:require [baz.woz :as woz :refer [one] :refer-macros [two]) |
| 23:26 | rberdeen | ah, it's http://dev.clojure.org/jira/browse/CLJS-785 |
| 23:28 | yedi | regarding environ: degrading to 0.4.0 seemed to fix my problem |
| 23:47 | yedi | how exactly do the cljsbuild ids work? |
| 23:48 | yedi | om 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? |