Re: Stubbing with instrument and generators
Thanks for taking a look. Here's a ticket: https://dev.clojure.org/jira/browse/CLJ-2197 > On 2017-06-30, at 11:52, Alex Miller <a...@puredanger.com> wrote: > > I don't think this is the same case as CLJ-2095 as the instrumented var > should have the opportunity to use the gen overrides you've included. In > particular, it seems like stest/instrument-choose-fn is currently passing the > :gen overrides map when getting the gen for the stubbed var. I'm wondering if > there is a bug there where the spec has already been resolved and thus the > gen key (::y) is not getting matched. Feel free to file a ticket for this. > > On Friday, June 30, 2017 at 9:37:42 AM UTC-5, Michael Glaesemann wrote: > Using spec instrument to stub functions is really helpful. I'm using stubbing > to test Stuart Sierra-style components with some success. However, I've been > surprised that generator override doesn't work as I would expect it to. > Here's an example: > > ;; [org.clojure/spec.alpha "0.1.123"] > > (require '[clojure.spec.alpha :as s]) > (require '[clojure.spec.gen.alpha :as gen]) > (require '[clojure.spec.test.alpha :as stest]) > > (defprotocol Y > (-do-y [r])) > > (def y? (partial satisfies? Y)) > (s/def ::y y?) > > ;; Protocol methods can't be spec'd, so wrap it in a function. > > (defn do-y [r] > (-do-y r)) > > (s/fdef do-y :args (s/cat :y-er ::y)) > > ;; Example of the protocol implementation that we're going to stub. > > (defrecord BadYer [] > Y > (-do-y [_] (throw (Exception. "can't make me!" > > > ;; Confirm BadYer instances are valid with respect to the protol spec. > > (s/valid? ::y (->BadYer)) > ;; => true > > ;; And confirm BadYer instances will throw when called. > > (try > (do-y (->BadYer)) > (catch Exception e > (.getMessage e))) > ;; => "can't make me!" > > > (def y-gen (gen/return (->BadYer))) > > ;; Confirm generator works as expected: > > (gen/sample y-gen 1) > ;; => (#spec_ex.core.BadYer{}) > > ;; We want to stub `do-y`, providing y-gen as a generator for `::y` > > (try > (stest/instrument `do-y {:stub #{`do-y} >:gen {::y (fn [] y-gen)}}) > (catch Exception e > (ex-data e))) > ;; => #:clojure.spec.alpha{:path [:y-er], :form :spec-ex.core/y, :failure > :no-gen} > > ;; However, we *can* stub `do-y` if we replace its spec. > > (stest/instrument `do-y > {:stub #{`do-y} >:spec {`do-y (s/fspec > :args (s/cat :y-er (s/with-gen ::y >(fn [] y-gen}}) > ;; => [spec-ex.core/do-y] > > There is a ticket open[ (CLJ-2095[1]) regarding using overrides s/gen with > custom generators. Is this a case where this applies? I can imagine that it > could be. Not overriding something that isn't there would result in the thing > still not being there, thus the :no-gen failure. And it is something that can > be worked around. It would be decidedly more succinct if the gen override > worked rather than the spec override. > > Best, > > Michael Glaesemann > grzm seespotcode net > > > [1]: https://dev.clojure.org/jira/browse/CLJ-2095 > > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with your > first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. Michael Glaesemann grzm seespotcode net -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Stubbing with instrument and generators
I don't think this is the same case as CLJ-2095 as the instrumented var should have the opportunity to use the gen overrides you've included. In particular, it seems like stest/instrument-choose-fn is currently passing the :gen overrides map when getting the gen for the stubbed var. I'm wondering if there is a bug there where the spec has already been resolved and thus the gen key (::y) is not getting matched. Feel free to file a ticket for this. On Friday, June 30, 2017 at 9:37:42 AM UTC-5, Michael Glaesemann wrote: > > Using spec instrument to stub functions is really helpful. I'm using > stubbing to test Stuart Sierra-style components with some success. However, > I've been surprised that generator override doesn't work as I would expect > it to. Here's an example: > > ;; [org.clojure/spec.alpha "0.1.123"] > > (require '[clojure.spec.alpha :as s]) > (require '[clojure.spec.gen.alpha :as gen]) > (require '[clojure.spec.test.alpha :as stest]) > > (defprotocol Y > (-do-y [r])) > > (def y? (partial satisfies? Y)) > (s/def ::y y?) > > ;; Protocol methods can't be spec'd, so wrap it in a function. > > (defn do-y [r] > (-do-y r)) > > (s/fdef do-y :args (s/cat :y-er ::y)) > > ;; Example of the protocol implementation that we're going to stub. > > (defrecord BadYer [] > Y > (-do-y [_] (throw (Exception. "can't make me!" > > > ;; Confirm BadYer instances are valid with respect to the protol spec. > > (s/valid? ::y (->BadYer)) > ;; => true > > ;; And confirm BadYer instances will throw when called. > > (try > (do-y (->BadYer)) > (catch Exception e > (.getMessage e))) > ;; => "can't make me!" > > > (def y-gen (gen/return (->BadYer))) > > ;; Confirm generator works as expected: > > (gen/sample y-gen 1) > ;; => (#spec_ex.core.BadYer{}) > > ;; We want to stub `do-y`, providing y-gen as a generator for `::y` > > (try > (stest/instrument `do-y {:stub #{`do-y} >:gen {::y (fn [] y-gen)}}) > (catch Exception e > (ex-data e))) > ;; => #:clojure.spec.alpha{:path [:y-er], :form :spec-ex.core/y, :failure > :no-gen} > > ;; However, we *can* stub `do-y` if we replace its spec. > > (stest/instrument `do-y > {:stub #{`do-y} >:spec {`do-y (s/fspec > :args (s/cat :y-er (s/with-gen ::y >(fn [] y-gen}}) > ;; => [spec-ex.core/do-y] > > There is a ticket open[ (CLJ-2095[1]) regarding using overrides s/gen with > custom generators. Is this a case where this applies? I can imagine that it > could be. Not overriding something that isn't there would result in the > thing still not being there, thus the :no-gen failure. And it is something > that can be worked around. It would be decidedly more succinct if the gen > override worked rather than the spec override. > > Best, > > Michael Glaesemann > grzm seespotcode net > > > [1]: https://dev.clojure.org/jira/browse/CLJ-2095 > > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Stubbing with instrument and generators
Using spec instrument to stub functions is really helpful. I'm using stubbing to test Stuart Sierra-style components with some success. However, I've been surprised that generator override doesn't work as I would expect it to. Here's an example: ;; [org.clojure/spec.alpha "0.1.123"] (require '[clojure.spec.alpha :as s]) (require '[clojure.spec.gen.alpha :as gen]) (require '[clojure.spec.test.alpha :as stest]) (defprotocol Y (-do-y [r])) (def y? (partial satisfies? Y)) (s/def ::y y?) ;; Protocol methods can't be spec'd, so wrap it in a function. (defn do-y [r] (-do-y r)) (s/fdef do-y :args (s/cat :y-er ::y)) ;; Example of the protocol implementation that we're going to stub. (defrecord BadYer [] Y (-do-y [_] (throw (Exception. "can't make me!" ;; Confirm BadYer instances are valid with respect to the protol spec. (s/valid? ::y (->BadYer)) ;; => true ;; And confirm BadYer instances will throw when called. (try (do-y (->BadYer)) (catch Exception e (.getMessage e))) ;; => "can't make me!" (def y-gen (gen/return (->BadYer))) ;; Confirm generator works as expected: (gen/sample y-gen 1) ;; => (#spec_ex.core.BadYer{}) ;; We want to stub `do-y`, providing y-gen as a generator for `::y` (try (stest/instrument `do-y {:stub #{`do-y} :gen {::y (fn [] y-gen)}}) (catch Exception e (ex-data e))) ;; => #:clojure.spec.alpha{:path [:y-er], :form :spec-ex.core/y, :failure :no-gen} ;; However, we *can* stub `do-y` if we replace its spec. (stest/instrument `do-y {:stub #{`do-y} :spec {`do-y (s/fspec :args (s/cat :y-er (s/with-gen ::y (fn [] y-gen}}) ;; => [spec-ex.core/do-y] There is a ticket open[ (CLJ-2095[1]) regarding using overrides s/gen with custom generators. Is this a case where this applies? I can imagine that it could be. Not overriding something that isn't there would result in the thing still not being there, thus the :no-gen failure. And it is something that can be worked around. It would be decidedly more succinct if the gen override worked rather than the spec override. Best, Michael Glaesemann grzm seespotcode net [1]: https://dev.clojure.org/jira/browse/CLJ-2095 -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Custom generators for custom predicate functions
Thanks Alex. I agree it probably isn't "needed", was just a little surprised to discover the asymmetry. Mostly was curious if there was some deeper design decision, e.g. that you need to start with some set of primitive predicates upon which you can start building named specs. On Thursday, December 8, 2016 at 9:23:11 AM UTC-8, Alex Miller wrote: > > In general, you shouldn't need to do this (it is better to attach the > generator to the spec). Generator mappings are provided for core Clojure > predicates so that many common predicates gen automatically and so that > they can be combined (via things like s/and) with other predicates that > filter but don't gen. > > I was not part of the design discussion, but I assume that it would open a > can of worms around conflicts, ordering, and function resolution that Rich > and Stu didn't want to open at this time. Nothing precludes this from being > expanded later if deemed useful. > > On Thursday, December 8, 2016 at 10:56:29 AM UTC-6, Dave Dixon wrote: >> >> Though one can obviously attach a custom generator to a keyword-named >> spec, it appears there is no way to do the same for a custom predicate >> function. I see that the generators for predicate functions testing for >> core primitives are hard-coded in the private >> clojure.spec.gen\gen-builtins. Curious why this isn't extensible, since it >> naively seems similar to the keyword case, but with the custom generator >> keyed by a symbol rather than a map. >> >> Dave >> > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Custom generators for custom predicate functions
In general, you shouldn't need to do this (it is better to attach the generator to the spec). Generator mappings are provided for core Clojure predicates so that many common predicates gen automatically and so that they can be combined (via things like s/and) with other predicates that filter but don't gen. I was not part of the design discussion, but I assume that it would open a can of worms around conflicts, ordering, and function resolution that Rich and Stu didn't want to open at this time. Nothing precludes this from being expanded later if deemed useful. On Thursday, December 8, 2016 at 10:56:29 AM UTC-6, Dave Dixon wrote: > > Though one can obviously attach a custom generator to a keyword-named > spec, it appears there is no way to do the same for a custom predicate > function. I see that the generators for predicate functions testing for > core primitives are hard-coded in the private > clojure.spec.gen\gen-builtins. Curious why this isn't extensible, since it > naively seems similar to the keyword case, but with the custom generator > keyed by a symbol rather than a map. > > Dave > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Custom generators for custom predicate functions
Though one can obviously attach a custom generator to a keyword-named spec, it appears there is no way to do the same for a custom predicate function. I see that the generators for predicate functions testing for core primitives are hard-coded in the private clojure.spec.gen\gen-builtins. Curious why this isn't extensible, since it naively seems similar to the keyword case, but with the custom generator keyed by a symbol rather than a map. Dave -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Spec & test.check generators for complex data structures
The general approach to this is to first create a "model" of your domain, which might be some random seed info and then generate one or more entities that are consistent with the model. Stu does a simple example of this in http://blog.cognitect.com/blog/2016/8/10/clojure-spec-screencast-customizing-generators using gen/fmap and gen/bind which is probably the best way to build something like this. As an example, if you need to test on a graph of nodes, your model might consist of first creating random nodes, then generating random edges between the nodes (rather than randomly generating nodes and edges, which will likely have no commonality). On Tuesday, November 1, 2016 at 2:14:28 PM UTC-5, Maarten Truyens wrote: > > Completely convinced of Spec, I am diving into property-based testing with > test.check. However, I encounter some difficulties for which I would like > to get the community's input. > > The central part of the software I am developing, consists of a tree of > different kinds of nodes that can refer to — and interact with — each > other. There are many business rules that specify how those nodes can > interact — e.g., a node of type A can refer to other nodes of types B and C > (but not D); or a node can have max. 3 child nodes of type E but more than > 3 child nodes of type F. > > It is trivial to have Spec generate completely random nodes to test > functions that can ignore the business rules. However, other functions do > depend on the business rules, and for those it is necessary to somewhat > "guide" the generators towards random-but-compliant output. And here I'm > stumbling: due to the business rules' complexity, this is not a matter of > simply inserting a few such-that generators, so that I have already spent > many days on writing a business rule compliant generator. Part of this is > due to the multitude and complexity of the business rules, part due to the > difficulty of writing generators (which operate at a higher level of > abstraction, and for which only a subset of the normal Clojure constructs > can be used). > > How do others cope with this issue? I have the feeling that I am pushing > the generators far beyond what they were designed to do, but at the same I > have to acknowledge that the time required to write traditional tests for > functions dealing with the business rules is also substantial — so maybe > the time required to write those generators is not abnormal. > > Any suggestions are welcomed! I did not find any in-depth observations of > other developers about property-based testing on the Net. > > Maarten > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Spec & test.check generators for complex data structures
Thanks - the start of that thread was indeed interesting, but it quickly changed course towards a discussion on whether Spec should check function outputs. Rich hinted at exactly the kind of in-depth discussion I wanted to find — but much too briefly... -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Spec & test.check generators for complex data structures
I don’t have any answers, but you might find the discussion in the first several messages of this thread <https://groups.google.com/d/topic/clojure/jcVnjk1MOWY/discussion> to be relevant. On Tuesday, November 1, 2016 at 3:14:28 PM UTC-4, Maarten Truyens wrote: > > Completely convinced of Spec, I am diving into property-based testing with > test.check. However, I encounter some difficulties for which I would like > to get the community's input. > > The central part of the software I am developing, consists of a tree of > different kinds of nodes that can refer to — and interact with — each > other. There are many business rules that specify how those nodes can > interact — e.g., a node of type A can refer to other nodes of types B and C > (but not D); or a node can have max. 3 child nodes of type E but more than > 3 child nodes of type F. > > It is trivial to have Spec generate completely random nodes to test > functions that can ignore the business rules. However, other functions do > depend on the business rules, and for those it is necessary to somewhat > "guide" the generators towards random-but-compliant output. And here I'm > stumbling: due to the business rules' complexity, this is not a matter of > simply inserting a few such-that generators, so that I have already spent > many days on writing a business rule compliant generator. Part of this is > due to the multitude and complexity of the business rules, part due to the > difficulty of writing generators (which operate at a higher level of > abstraction, and for which only a subset of the normal Clojure constructs > can be used). > > How do others cope with this issue? I have the feeling that I am pushing > the generators far beyond what they were designed to do, but at the same I > have to acknowledge that the time required to write traditional tests for > functions dealing with the business rules is also substantial — so maybe > the time required to write those generators is not abnormal. > > Any suggestions are welcomed! I did not find any in-depth observations of > other developers about property-based testing on the Net. > > Maarten > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Spec & test.check generators for complex data structures
Completely convinced of Spec, I am diving into property-based testing with test.check. However, I encounter some difficulties for which I would like to get the community's input. The central part of the software I am developing, consists of a tree of different kinds of nodes that can refer to — and interact with — each other. There are many business rules that specify how those nodes can interact — e.g., a node of type A can refer to other nodes of types B and C (but not D); or a node can have max. 3 child nodes of type E but more than 3 child nodes of type F. It is trivial to have Spec generate completely random nodes to test functions that can ignore the business rules. However, other functions do depend on the business rules, and for those it is necessary to somewhat "guide" the generators towards random-but-compliant output. And here I'm stumbling: due to the business rules' complexity, this is not a matter of simply inserting a few such-that generators, so that I have already spent many days on writing a business rule compliant generator. Part of this is due to the multitude and complexity of the business rules, part due to the difficulty of writing generators (which operate at a higher level of abstraction, and for which only a subset of the normal Clojure constructs can be used). How do others cope with this issue? I have the feeling that I am pushing the generators far beyond what they were designed to do, but at the same I have to acknowledge that the time required to write traditional tests for functions dealing with the business rules is also substantial — so maybe the time required to write those generators is not abnormal. Any suggestions are welcomed! I did not find any in-depth observations of other developers about property-based testing on the Net. Maarten -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: clojure.spec.test/instrument causes clojure.spec/exercise-fn to use generators which fail the args spec!?
Ah, I missed thatthank you very much! -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: clojure.spec.test/instrument causes clojure.spec/exercise-fn to use generators which fail the args spec!?
You have two possible branches for your ::fizbuzz arguments, a one-arity and a 3-arity. The 1-arity branch allows for the value 1, which when passed to the function fizzbuzz recursively calls the function fizzbuzz with the arguments (3 5 1) is not a valid set of values for ::fizzbuzz and so raises an exception. The reason you only get the exception when you've instrumented the function, is because the non-conforming set of arguments is constructed in the 1-arity, and doesn't get checked against ::fizzbuzz unless instrumentation is turned on. On Thursday, October 20, 2016 at 3:17:19 PM UTC+11, J.-F. Rompre wrote: > > I am trying to learn clojure.spec and tried my hand at a spec for a > fizzbuzz function. > For some strange reason, generators created for it fail the same spec > during clojure.spec/exercise-fn ! > > Stranger, this happens only if the same function is first instrumented > using clojure.spec.stest/instrument. > Otherwise (commenting out the instrument call), exercise-fn generates > compliant inputs and returns. > > I tried to reproduce this with a trivial example to show here but > couldn't, so created a gist to illustrate the issue: > https://gist.github.com/KingCode/101ff425f1abd9693a7e8c4b5d389e74 > > Thanks for any comment and enlightening, I can't wait to use spec > productively :) > JF > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
clojure.spec.test/instrument causes clojure.spec/exercise-fn to use generators which fail the args spec!?
I am trying to learn clojure.spec and tried my hand at a spec for a fizzbuzz function. For some strange reason, generators created for it fail the same spec during clojure.spec/exercise-fn ! Stranger, this happens only if the same function is first instrumented using clojure.spec.stest/instrument. Otherwise (commenting out the instrument call), exercise-fn generates compliant inputs and returns. I tried to reproduce this with a trivial example to show here but couldn't, so created a gist to illustrate the issue: https://gist.github.com/KingCode/101ff425f1abd9693a7e8c4b5d389e74 Thanks for any comment and enlightening, I can't wait to use spec productively :) JF -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Q: Is there a reason why some clojure.test.check generators are excluded from clojure.spec.gen lazy primitives?
Is there a reason why some clojure.test.check generators are excluded from clojure.spec.gen lazy primitives? https://github.com/clojure/clojure/blob/1f25347a7b219488d5d9f8d17b04f2cc7828b30e/src/clj/clojure/spec/gen.clj#L114 The nat generator as one example is missing. Best regards, Joe N -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
clojure.spec guide updated with generators
I've added a new section to the clojure.spec guide for generators. Certainly doesn't cover everything yet but hope it helps! http://clojure.org/guides/spec#_generators -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[ANN] schema-generators 0.1.0 (now with ClojureScript!)
We've released schema-generators 0.1.0, which includes ClojureScript support via cljc: https://github.com/plumatic/schema-generators This library allows you to generate test data from most plumatic/schemas out of the box, as well as automatically "complete" partial datums -- which can both be very useful in different testing scenarios. Please note the the corresponding functionality is now deprecated in the main schema project. Big thanks to Milton Reder and others who helped with this release! And on this note, *schema, plumbing, and our other libraries are now a completely volunteer effort, with no commercial support*. Any help the community can provide in triaging issues, fixing bugs, etc would be much appreciated -- especially on the ClojureScript side of things. If you're interested in helping out, please let me know and I'm happy to provide suggestions for how to get started. Have fun, and please let us know your feedback! -Jason -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [ANN] boot-new 0.4.0 -- Templates AND Generators for Boot!
I have some feedback. Great work! I just blogged about a pure-boot way to get started with clojurescript: ( http://escherize.com/2016/02/29/boot-with-cljs ) so of course boot-new made an appearance. On Monday, February 29, 2016 at 12:20:50 PM UTC+11, Sean Corfield wrote: > > Frank Liu wrote on Saturday, February 27, 2016 at 9:39 AM: > > Love your project. Could you try to add them to the boot official pages > and github wiki's third party tasks? The reason is I can never find this > project on google (via "boot-new") or anywhere other than your github or > search here in the Clojure google group. > > > It is listed on the third party tasks wiki page: > > https://github.com/boot-clj/boot/wiki/Community-Tasks > > As: > > Templates (Boot new) seancorfield/boot-new > <https://github.com/seancorfield/boot-new> > > But the plan is to merge it into the core Boot project at some point (once > we get a bit more feedback on boot-new itself and its templates and > generators) to knock off any rough edges. > > Sean Corfield -- (904) 302-SEAN > An Architect's View -- http://corfield.org/ > > "If you're not annoying somebody, you're not really alive." > -- Margaret Atwood > > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [ANN] boot-new 0.4.0 -- Templates AND Generators for Boot!
Frank Liu wrote on Saturday, February 27, 2016 at 9:39 AM: Love your project. Could you try to add them to the boot official pages and github wiki's third party tasks? The reason is I can never find this project on google (via "boot-new") or anywhere other than your github or search here in the Clojure google group. It is listed on the third party tasks wiki page: https://github.com/boot-clj/boot/wiki/Community-Tasks As: Templates (Boot new)seancorfield/boot-new But the plan is to merge it into the core Boot project at some point (once we get a bit more feedback on boot-new itself and its templates and generators) to knock off any rough edges. Sean Corfield -- (904) 302-SEAN An Architect's View -- http://corfield.org/ "If you're not annoying somebody, you're not really alive." -- Margaret Atwood -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [ANN] boot-new 0.4.0 -- Templates AND Generators for Boot!
Hi Sean, Love your project. Could you try to add them to the boot official pages and github wiki's third party tasks? The reason is I can never find this project on google (via "boot-new") or anywhere other than your github or search here in the Clojure google group. Frank On Saturday, February 13, 2016 at 2:21:18 PM UTC-8, Sean Corfield wrote: > > What / Where? > Boot new — a task to produce new projects from Boot and/or Leiningen > templates! > boot-new 0.4.0 — https://github.com/seancorfield/boot-new > > Updates? > Now supports generators to add / modify code in the current project! > Add a new namespace with: boot new –g ns=foo.bar.quux > Add a new function with: boot new –g defn=foo.bar.quux/my-func > > Sean Corfield -- (904) 302-SEAN > An Architect's View -- http://corfield.org/ > > "Perfection is the enemy of the good." > -- Gustave Flaubert, French realist novelist (1821-1880) > > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[ANN] boot-new 0.4.0 -- Templates AND Generators for Boot!
What / Where? Boot new — a task to produce new projects from Boot and/or Leiningen templates! boot-new 0.4.0 — https://github.com/seancorfield/boot-new Updates? Now supports generators to add / modify code in the current project! Add a new namespace with: boot new –g ns=foo.bar.quux Add a new function with: boot new –g defn=foo.bar.quux/my-func Sean Corfield -- (904) 302-SEAN An Architect's View -- http://corfield.org/ "Perfection is the enemy of the good." -- Gustave Flaubert, French realist novelist (1821-1880) -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Controlling growth rates of generators with test.check
Nice. Any updates on this? Is this a good idea? On Friday, May 15, 2015 at 12:13:06 PM UTC+5:30, Mikera wrote: Hi all, I am doing some generative testing with test.check and need a way to control the growth rate of data structures (the regular linear growth quickly makes the computations too large for meaningful testing usage). I came up with the following solution to do this: (defn gen-resize Creates a generator that pre-modifies the 'size' pramater with the function f. Use if you want to have the size grow at a different rate from the normal linear scaling. ([f gen] (let [gf (or (:gen gen) gen paramter must be a test.check generator) new-gf (fn [rnd size] (gf rnd (f size)))] (clojure.test.check.generators.Generator. new-gf Normal O(n) growth: (gen/sample gen/s-pos-int 30) = (1 2 3 2 4 5 4 7 6 3 3 7 10 4 8 11 14 12 6 10 9 1 8 21 12 16 25 25 21 6) Controlled O(sqrt(n)) growth: (gen/sample (gen-resize sqrt gen/s-pos-int) 30) = (1 2 2 2 2 4 3 3 3 3 4 3 5 1 2 3 2 4 4 2 2 3 6 6 2 5 5 4 6 3) So it seems to work, but is this a sane / recommended approach? Am I relying too much on test.check internals? mikera -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Controlling growth rates of generators with test.check
See: https://github.com/clojure/test.check/commit/d4883873df73717629272d0ab71619d7e58c9c9e On Wednesday, 29 July 2015 23:31:14 UTC+8, Mayank Jain wrote: Nice. Any updates on this? Is this a good idea? On Friday, May 15, 2015 at 12:13:06 PM UTC+5:30, Mikera wrote: Hi all, I am doing some generative testing with test.check and need a way to control the growth rate of data structures (the regular linear growth quickly makes the computations too large for meaningful testing usage). I came up with the following solution to do this: (defn gen-resize Creates a generator that pre-modifies the 'size' pramater with the function f. Use if you want to have the size grow at a different rate from the normal linear scaling. ([f gen] (let [gf (or (:gen gen) gen paramter must be a test.check generator) new-gf (fn [rnd size] (gf rnd (f size)))] (clojure.test.check.generators.Generator. new-gf Normal O(n) growth: (gen/sample gen/s-pos-int 30) = (1 2 3 2 4 5 4 7 6 3 3 7 10 4 8 11 14 12 6 10 9 1 8 21 12 16 25 25 21 6) Controlled O(sqrt(n)) growth: (gen/sample (gen-resize sqrt gen/s-pos-int) 30) = (1 2 2 2 2 4 3 3 3 3 4 3 5 1 2 3 2 4 4 2 2 3 6 6 2 5 5 4 6 3) So it seems to work, but is this a sane / recommended approach? Am I relying too much on test.check internals? mikera -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Controlling growth rates of generators with test.check
Thanks. That looks useful. On Jul 30, 2015 6:14 AM, Mikera mike.r.anderson...@gmail.com wrote: See: https://github.com/clojure/test.check/commit/d4883873df73717629272d0ab71619d7e58c9c9e On Wednesday, 29 July 2015 23:31:14 UTC+8, Mayank Jain wrote: Nice. Any updates on this? Is this a good idea? On Friday, May 15, 2015 at 12:13:06 PM UTC+5:30, Mikera wrote: Hi all, I am doing some generative testing with test.check and need a way to control the growth rate of data structures (the regular linear growth quickly makes the computations too large for meaningful testing usage). I came up with the following solution to do this: (defn gen-resize Creates a generator that pre-modifies the 'size' pramater with the function f. Use if you want to have the size grow at a different rate from the normal linear scaling. ([f gen] (let [gf (or (:gen gen) gen paramter must be a test.check generator) new-gf (fn [rnd size] (gf rnd (f size)))] (clojure.test.check.generators.Generator. new-gf Normal O(n) growth: (gen/sample gen/s-pos-int 30) = (1 2 3 2 4 5 4 7 6 3 3 7 10 4 8 11 14 12 6 10 9 1 8 21 12 16 25 25 21 6) Controlled O(sqrt(n)) growth: (gen/sample (gen-resize sqrt gen/s-pos-int) 30) = (1 2 2 2 2 4 3 3 3 3 4 3 5 1 2 3 2 4 4 2 2 3 6 6 2 5 5 4 6 3) So it seems to work, but is this a sane / recommended approach? Am I relying too much on test.check internals? mikera -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Controlling growth rates of generators with test.check
Hi all, I am doing some generative testing with test.check and need a way to control the growth rate of data structures (the regular linear growth quickly makes the computations too large for meaningful testing usage). I came up with the following solution to do this: (defn gen-resize Creates a generator that pre-modifies the 'size' pramater with the function f. Use if you want to have the size grow at a different rate from the normal linear scaling. ([f gen] (let [gf (or (:gen gen) gen paramter must be a test.check generator) new-gf (fn [rnd size] (gf rnd (f size)))] (clojure.test.check.generators.Generator. new-gf Normal O(n) growth: (gen/sample gen/s-pos-int 30) = (1 2 3 2 4 5 4 7 6 3 3 7 10 4 8 11 14 12 6 10 9 1 8 21 12 16 25 25 21 6) Controlled O(sqrt(n)) growth: (gen/sample (gen-resize sqrt gen/s-pos-int) 30) = (1 2 2 2 2 4 3 3 3 3 4 3 5 1 2 3 2 4 4 2 2 3 6 6 2 5 5 4 6 3) So it seems to work, but is this a sane / recommended approach? Am I relying too much on test.check internals? mikera -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Howto write test.check custom generators
Hey Tim, When you write a property, like your `has-agroup`, there's no need to call `gen/sample`. You can simply write: (prop/for-all [v my-generator] ...) -Reid On Sunday, August 10, 2014 6:04:21 PM UTC-5, frye wrote: Oook, this is starting to sink in. I've gotten a little farther, in that I can run quick-check with my custom generator. However, after a bunch of values had been generated, it fails on a NullPointerException. How can I know where the breakdown is happening? = (tc/quick-check 100 u/has-agroup) {:email , :last-name , :first-name , :username } {:email , :last-name , :first-name , :username 0} {:email , :last-name , :first-name Rq, :username 0} {:email 5D2, :last-name R4F, :first-name x, :username G0H} ... {:email 8KQgSr497EPw14X80oEbWC0, :last-name cdkLb8D5ol, :first-name 8DCOXz1U4S3JM641u5I7yPwQ, :username DADOk} {:email x, :last-name Qq3h07d6Cbs4, :first-name 6H6Enrwu, :username yf40SClLjJHp1ptbnx4I9xFbwI3} *NullPointerException clojure.test.check.generators/gen-bind/fn--18990 (generators.clj:77)* bkell.bkell (pst *e) NullPointerException clojure.test.check.generators/gen-bind/fn--18990 (generators.clj:77) clojure.test.check.generators/gen-bind/fn--18990 (generators.clj:79) clojure.test.check.generators/gen-bind/fn--18990 (generators.clj:77) clojure.test.check.generators/gen-fmap/fn--18985 (generators.clj:70) clojure.test.check.generators/call-gen (generators.clj:56) clojure.test.check/quick-check (check.clj:57) bkell.bkell/eval19267 (form-init7280611083923741467.clj:1) clojure.lang.Compiler.eval (Compiler.java:6703) clojure.lang.Compiler.eval (Compiler.java:) clojure.core/eval (core.clj:2927) clojure.main/repl/read-eval-print--6625/fn--6628 (main.clj:239) clojure.main/repl/read-eval-print--6625 (main.clj:239) This is my domain function: (defn *create-user* ([] (create {})) ([opts] (println opts) (let [sans-nils (apply merge (for [[k v] opts :when (not (nil? v))] {k v}))] (merge {:id (mu/generate-uuid) :username :password (crypto/base64 12) :first-name :last-name :email :country {}} sans-nils And these are my test functions. (def gend-user (gen/fmap *du/create-user* (gen/hash-map :username gen/string-alpha-numeric :first-name gen/string-alpha-numeric :last-name gen/string-alpha-numeric :email gen/string-alpha-numeric))) (def has-agroup (prop/for-all [v (gen/sample gend-user)] (- v nil? not))) Tim Washington Interruptsoftware.com http://interruptsoftware.com On Sun, Aug 10, 2014 at 3:02 PM, Sam Ritchie sritc...@gmail.com javascript: wrote: You can to use gen/fmap to build up generators. Here's an example: -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Howto write test.check custom generators
Hi there, I'm trying to get my head wrapped around test.check https://github.com/clojure/test.check/. My current stumbling block is custom generators. Of course I've combed through the docs https://github.com/clojure/test.check/blob/master/doc/intro.md#record-generators and source https://github.com/clojure/test.check/blob/master/src/main/clojure/clojure/test/check/generators.clj. And I'm pretty sure I need to use *gen-bind* to get this all working. But it's just not clicking yet. Let's say I want to create a *user* and a *group*, where a user can belong to many groups. So let's say I have a generic *create-user* function. (defn *create-user* [opts] (merge {:id (mu/generate-uuid) :username :password (crypto/base64 12) :first-name :last-name :email :country {}} opts)) And a generic *create-group* function. (defn create [opts] (merge {:id (mu/generate-uuid) :name :users []} opts)) 1. Now, if I try `*(gen/sample create-user)*`, or `*(gen/sample (gen/vector du/create))*`it will fail. 2. I also want to do the same thing with groups (ie *(gen/sample create-user)*). 3. Additionally however, I want to assert that a created group will always have at least 1 user in the `*:users []*` k/v field. How can I make test.check generators for these data structures? Tim Washington Interruptsoftware.com http://interruptsoftware.com -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Howto write test.check custom generators
You can to use gen/fmap to build up generators. Here's an example: ;; generates a millisecond using gen/choose, then maps that to a time instance using my u/ms-to-time function. (def result-gen (- (gen/choose 0 u/max-time) (gen/fmap u/ms-to-time))) ;; Generates EITHER a result or nil, then maps that into an event entry data structure: (def event-entry-gen (- (gen/one-of [(gen/return nil) result-gen]) (gen/fmap (fn [result] (merge {:_id id :_rev rev :type event-entry :division {:age-group U17 :boat-type K1 :gender male} :event-id event-id :regatta-id regatta-id :athletes [] :racer-number 10} (when result {:result {:division-size 10 :rank {:overall 1 :division 1} :time result}})) Once you have a generator instance you can copy the rest of the test.check examples, run gen/sample on the generator directly... all the good stuff. Timothy Washington mailto:twash...@gmail.com August 10, 2014 at 12:38 PM Hi there, I'm trying to get my head wrapped around test.check https://github.com/clojure/test.check/. My current stumbling block is custom generators. Of course I've combed through the docs https://github.com/clojure/test.check/blob/master/doc/intro.md#record-generators and source https://github.com/clojure/test.check/blob/master/src/main/clojure/clojure/test/check/generators.clj. And I'm pretty sure I need to use */gen-bind/* to get this all working. But it's just not clicking yet. Let's say I want to create a */user/* and a */group/*, where a user can belong to many groups. So let's say I have a generic */create-user/* function. (defn */create-user/* [opts] (merge {:id (mu/generate-uuid) :username :password (crypto/base64 12) :first-name :last-name :email :country {}} opts)) And a generic */create-group/* function. (defn create [opts] (merge {:id (mu/generate-uuid) :name :users []} opts)) 1. Now, if I try `*/(gen/sample create-user)/*`, or `*/(gen/sample (gen/vector du/create))/*`it will fail. 2. I also want to do the same thing with groups (ie /(gen/sample create-user)/). 3. Additionally however, I want to assert that a created group will always have at least 1 user in the `*/:users []/*` k/v field. How can I make test.check generators for these data structures? Tim Washington Interruptsoftware.com http://interruptsoftware.com -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com mailto:clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. -- Sam Ritchie (@sritchie) Paddleguru Co-Founder 703.863.8561 www.paddleguru.com http://www.paddleguru.com/ Twitter http://twitter.com/paddleguru// Facebook http://facebook.com/paddleguru -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Howto write test.check custom generators
Oook, this is starting to sink in. I've gotten a little farther, in that I can run quick-check with my custom generator. However, after a bunch of values had been generated, it fails on a NullPointerException. How can I know where the breakdown is happening? = (tc/quick-check 100 u/has-agroup) {:email , :last-name , :first-name , :username } {:email , :last-name , :first-name , :username 0} {:email , :last-name , :first-name Rq, :username 0} {:email 5D2, :last-name R4F, :first-name x, :username G0H} ... {:email 8KQgSr497EPw14X80oEbWC0, :last-name cdkLb8D5ol, :first-name 8DCOXz1U4S3JM641u5I7yPwQ, :username DADOk} {:email x, :last-name Qq3h07d6Cbs4, :first-name 6H6Enrwu, :username yf40SClLjJHp1ptbnx4I9xFbwI3} *NullPointerException clojure.test.check.generators/gen-bind/fn--18990 (generators.clj:77)* bkell.bkell (pst *e) NullPointerException clojure.test.check.generators/gen-bind/fn--18990 (generators.clj:77) clojure.test.check.generators/gen-bind/fn--18990 (generators.clj:79) clojure.test.check.generators/gen-bind/fn--18990 (generators.clj:77) clojure.test.check.generators/gen-fmap/fn--18985 (generators.clj:70) clojure.test.check.generators/call-gen (generators.clj:56) clojure.test.check/quick-check (check.clj:57) bkell.bkell/eval19267 (form-init7280611083923741467.clj:1) clojure.lang.Compiler.eval (Compiler.java:6703) clojure.lang.Compiler.eval (Compiler.java:) clojure.core/eval (core.clj:2927) clojure.main/repl/read-eval-print--6625/fn--6628 (main.clj:239) clojure.main/repl/read-eval-print--6625 (main.clj:239) This is my domain function: (defn *create-user* ([] (create {})) ([opts] (println opts) (let [sans-nils (apply merge (for [[k v] opts :when (not (nil? v))] {k v}))] (merge {:id (mu/generate-uuid) :username :password (crypto/base64 12) :first-name :last-name :email :country {}} sans-nils And these are my test functions. (def gend-user (gen/fmap *du/create-user* (gen/hash-map :username gen/string-alpha-numeric :first-name gen/string-alpha-numeric :last-name gen/string-alpha-numeric :email gen/string-alpha-numeric))) (def has-agroup (prop/for-all [v (gen/sample gend-user)] (- v nil? not))) Tim Washington Interruptsoftware.com http://interruptsoftware.com On Sun, Aug 10, 2014 at 3:02 PM, Sam Ritchie sritchi...@gmail.com wrote: You can to use gen/fmap to build up generators. Here's an example: -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Advice on managing random number generators across threads
Keep in mind that there could be accuracy reasons why you might want to use multiple random number generators (aka multiple streams). See the section Single Versus Multiple Streams here: http://www.cse.msu.edu/~cse808/CSIM_Notes03/cse808/html_c/16random.htm Also, the built in java random number generator is ok, but not state-of-the-art in terms of quality. A more popular high quality generator is the Mersenne twister. There are several java implementations available. On Friday, June 6, 2014 11:33:04 PM UTC-4, Mars0i wrote: Wow. Linus, thanks for the very detailed answer. It sounds as your view is that there's no problem with the logic of my proposed solution, but it seems wasteful to create 100 RNGs, when I don't actually need to have so many of them. Your solutions provide ways to get the same result without maintaining so many RNG objects in a simulation run. Is that roughly correct? On Friday, June 6, 2014 2:26:25 PM UTC-5, Linus Ericsson wrote: (I think your stepwise problem is better to be solved without agents, see below.) I realized that the *rng* actually is conflated, it keeps both the state for the random number generator AND the algorithm used for the random number generation. This is usually not a problem, since the state-size and usage is dependent on the particular random number generator, but it becomes a problem when we need to separate and multithread things Interesting point. OK. But seem my comment below about sharing of code between RNG objects. One solution would be to either re-implement the algorithm (by Knuth) used in the original Sun Java random implementation, or use the experimental library Four [1] by Gary Fredericks that does exactly this. Four looks very nice. Its stateless RNGs return a new RNG, rather than an RNG state, btw: (class (rs/java-random 1001)) ;== four.stateless.JavaRandom (map class (rs/next-long (rs/java-random 1001))) ;== (java.lang.Long four.stateless.JavaRandom) I can see how this might be useful, though. What you would like to do is to be able to feed the rng-algorithm with the state (it is just a 64 bit long), and simply take the random-result generated from it, and store the state in the agent together with the rest of the simulation state. Dubious Speculations: This makes it necessary to know that the agents are called in the same order (if the influence on each other). Given the non-guarantee of ordering in the nature of Java Threads and how agents rely on them I don't think you can expect your result to be reproducible. Right. I can guarantee the order in which the random numbers are used when I use map to cause each person to do its work, but I assume that I can't guarantee this order when I use pmap. Here I assume that the incoming calls to agents aren't guaranteed to strictly ordered among different agents, even though the agents reside in one of two thread-pools (the send- vs. send-off pools). If two agents sent messages that arrived a third agent in different order, the rng-state would differ between the runs). Please correct me if I'm wrong on this one. No, there's no issue about the order in which messages are received, I believe. Communication is effectively simultaneous, because all sending happens in one step, and all receiving happens in another step. (Here are the details, if you're interested: Each Person random chooses other Persons to send a message to, and then randomly chooses a message to send. The pmap over the Persons ends, and all of the messages are collected into a single hashmap. Then a separate pmap goes through each Person, applying the messages in the hashmap that are supposed to be sent to that Person. Thus, although Persons perform their work in some order, the sending and the receiving of the messages are separated, so that message sending and receipt occurs as if all messages were sent simultaneously. In the next timestep, the messages received by a Person affect the probabilities that various messages will be chosen to send to another Person.) A possible clever way around this could be to send the rng state together with the message arriving at the agent, to make the agent at least react to the state in a similar way. Interesting idea. I don't think I'll need this, though. If you have some kind of continous magnitudes in the simulation - like pheromones - the simulation would maybe converge to similar results since the interaction effects would be reproducible but this is indeed a very far-fetched hypothesis. The simulation converges, but the same parameters can allow convergence to different outcomes. I usually have to run the simulation many times with the same parameters so that I can get a frequency distribution over outcomes. So only if your Person transform functions are commutative (ie gives the same result whichever
Re: Advice on managing random number generators across threads
On Saturday, June 7, 2014 7:09:53 PM UTC-5, Alexander Hudek wrote: Keep in mind that there could be accuracy reasons why you might want to use multiple random number generators (aka multiple streams). See the section Single Versus Multiple Streams here: http://www.cse.msu.edu/~cse808/CSIM_Notes03/cse808/html_c/16random.htm Very nice--thanks. I had never heard of this issue, but it makes sense. Also, the built in java random number generator is ok, but not state-of-the-art in terms of quality. A more popular high quality generator is the Mersenne twister. There are several java implementations available. That's what I thought, and I was leaning toward using a Mersenne twister. An additional advantage of sampling libraries like data.generators and bigml/sampling that allow one to specify the RNG is the ability to use a different RNG algorithm. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Advice on managing random number generators across threads
I'm writing an agent-based simulation framework, in which agents are Clojure records called Persons. There are 40-100 persons at present, but conceivably the number could go up to 1000. In each timestep, Persons' states are functionally updated by mapping update functions across the collection of Persons. The application is designed to be able to run in a single thread, or to be run in multiple threads, depending on whether I do the mapping using map or pmap. (The application is generally faster with pmap (and all I had to do was add p), but I think there might be contexts in which single-threaded operation is preferable.) At one point in the Person-update process, each Person randomly samples a small number (1 to 50) of elements from some small collections (size 10 up to the max number of persons). When the application is multi-threaded, I'd rather not have separate threads accessing the same random number generator. (Java 1.7 allows a way of dealing with that, but for now I'd rather be compatible with Java 1.6 as well.) Does the following solution make sense? 1. During initialization, I'll get a random number generator from java.util.Random, initialized with the system time or something else that varies. 2. I'll give each person a field :rng, and will initialize each one with a sparate call to java.util.Random, with a seed determined by the RNG mentioned in the previous line. (After this I can let the inititial RNG to be garbage collected.) 3. During the steps in which each Person needs to sample from collections, the code will get the RNG from the Person's :rng file, and use it to determine what elements are sampled. There is more than one way that I could implement step 3. Here are some options I'm considering: (a) Bind data.generators/*rnd* to the RNG, and then call functions in data.generators http://clojure.github.io/data.generators/. (b) Pass the Person's RNG to functions from bigml/sampling https://github.com/bigmlcom/sampling (which allow you to pass in an RNG). (c) Write my own sampling functions that use the RNG from the Person. Further remarks: When the application is single-threaded, each Person will use a different RNG, which isn't necessary, but it won't hurt, since the RNGs will have different seeds, except that I waste memory by creating multiple RNGs. When the application is multi-threaded, I still don't need one RNG per person, strictly speaking, since the number of threads will be much less than the number of Persons. However, giving each Person its own RNG is simpler. It means that my code can ignore threads and let Clojure figure out how to manage them. What do you think? Thanks in advance for any help. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Advice on managing random number generators across threads
One more point: I would save the system-time-determined seed of the initial RNG to a file (i.e. the RNG used to generate seeds for each Person's RNG). I believe this will allow me to re-run a simulation with identical results, by seeding the initial RNG with the seed saved from the previous simulation run. Let me know if this doesn't make sense. Thanks. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Advice on managing random number generators across threads
In Java 7 you would use ThreadLocalRandom you said in another thread. Well, in Java 6 you already have ThreadLocal [1] and thus you are able to build a thread local Random yourself to keep Java 6 as minimum requirement. [1] http://docs.oracle.com/javase/6/docs/api/index.html?java/lang/ThreadLocal.html -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Advice on managing random number generators across threads
On Friday, June 6, 2014 2:05:16 PM UTC-5, Gunnar Völkel wrote: In Java 7 you would use ThreadLocalRandom you said in another thread. Well, in Java 6 you already have ThreadLocal [1] and thus you are able to build a thread local Random yourself to keep Java 6 as minimum requirement. [1] http://docs.oracle.com/javase/6/docs/api/index.html?java/lang/ThreadLocal.html OK, that's good to know. Great. I may use that. Thanks Gunnar. I still wonder whether the scheme I outlined would be a good strategy for preventing delays due to contention by different threads for the same RNG. In my scheme, none of the RNGs would actually be local to threads. Each would be globally accessible in principle, but no RNG would be accessed from more than one thread at a time. (I like keeping things simple, but maybe I'm being simplistic.) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Advice on managing random number generators across threads
(I think your stepwise problem is better to be solved without agents, see below.) I realized that the *rng* actually is conflated, it keeps both the state for the random number generator AND the algorithm used for the random number generation. This is usually not a problem, since the state-size and usage is dependent on the particular random number generator, but it becomes a problem when we need to separate and multithread things. One solution would be to either re-implement the algorithm (by Knuth) used in the original Sun Java random implementation, or use the experimental library Four [1] by Gary Fredericks that does exactly this. What you would like to do is to be able to feed the rng-algorithm with the state (it is just a 64 bit long), and simply take the random-result generated from it, and store the state in the agent together with the rest of the simulation state. Dubious Speculations: This makes it necessary to know that the agents are called in the same order (if the influence on each other). Given the non-guarantee of ordering in the nature of Java Threads and how agents rely on them I don't think you can expect your result to be reproducible. Here I assume that the incoming calls to agents aren't guaranteed to strictly ordered among different agents, even though the agents reside in one of two thread-pools (the send- vs. send-off pools). If two agents sent messages that arrived a third agent in different order, the rng-state would differ between the runs). Please correct me if I'm wrong on this one. A possible clever way around this could be to send the rng state together with the message arriving at the agent, to make the agent at least react to the state in a similar way. If you have some kind of continous magnitudes in the simulation - like pheromones - the simulation would maybe converge to similar results since the interaction effects would be reproducible but this is indeed a very far-fetched hypothesis. So only if your Person transform functions are commutative (ie gives the same result whichever order they was called in every timestep) the simulation could be reproducible by storing the local random generator seed in each Person. If it's just speed you are after, do use either the java 1.7 ThreadLocalRandom (at least try out if this really gives any performance boost). A naive ThreadLocalImplementation implementation of clojure.core/rand would be: (defn rand Returns a random floating point number between 0 (inclusive) and n (default 1) (exclusive). {:added 1.0 :static true} * ([] (.nextDouble (java.util.concurrent.ThreadLocalRandom/current)))* ([n] (* n (rand but as you can see in the source code, random integers are generated using a call to (rand), multiplied with the integer and floored (when converting to int), so there are ways to get an limited range int more efficiently (check the source code for java.util.Random, which makes various tricks for getting just enough random bits out. As always, measure performance (Hugo Duncans Criterium, criterium.core/bench is a really good start). Numerical double operations are cheap, memory accesses - in this case to resulting data structures or other agents and likely context switches - could as well be the more expensive part. BTW: It looks like the problem you want to solve would benefit much from being formulated as a two-step problem, one where you applied all the incoming calls to each Person, and another where you sorted the messages to each Person in some reproducible order, like * = has an incoming message initial state: Person A will hit Person B, just for the lulz. apply map: A* B C resulting actions sorted by Receiver: [A hits B] apply these: A B* C [B gets mad and throw raspberry pies at both A and C] A* B C* [A yells at B, C yells at B] - mind the ordering! Always apply A's action before Cs (or let B's random seed shuffle a sorted ordering of the same to avoid ordering biases and make it reproducible) A B* C [B sends a stern look to A and C] no further actions If you makes the message passing explicit instead of Java-thread-call-uncertain-implicit (which IS possible and parallelizeable in a stepwise simulation!) you can still parallelize it in many ways (for example with reducers) and at the same time make simulations reproducible, and you'll avoid a lot (N²) of potentially expensive context switching. /Linus - take everything I say with a sand-pile avalanche of salt-grains. [1] https://github.com/fredericksgary/four 2014-06-06 18:37 GMT+02:00 Mars0i marsh...@logical.net: One more point: I would save the system-time-determined seed of the initial RNG to a file (i.e. the RNG used to generate seeds for each Person's RNG). I believe this will allow me to re-run a simulation with identical results, by seeding the initial RNG with the seed saved from the previous simulation run. Let me know if this doesn't make sense. Thanks. -- You received this message because you are subscribed to
Re: Advice on managing random number generators across threads
I don't know if this will be helpful in your application, or even if it's the best approach for our own work (or if java 1.7 provides a simpler approach?), but FWIW one of my projects deals with the thread-local RNG issue via: https://clojars.org/clj-random -Lee On Jun 6, 2014, at 12:28 PM, Mars0i marsh...@logical.net wrote: I'm writing an agent-based simulation framework, in which agents are Clojure records called Persons. There are 40-100 persons at present, but conceivably the number could go up to 1000. In each timestep, Persons' states are functionally updated by mapping update functions across the collection of Persons. The application is designed to be able to run in a single thread, or to be run in multiple threads, depending on whether I do the mapping using map or pmap. (The application is generally faster with pmap (and all I had to do was add p), but I think there might be contexts in which single-threaded operation is preferable.) At one point in the Person-update process, each Person randomly samples a small number (1 to 50) of elements from some small collections (size 10 up to the max number of persons). When the application is multi-threaded, I'd rather not have separate threads accessing the same random number generator. (Java 1.7 allows a way of dealing with that, but for now I'd rather be compatible with Java 1.6 as well.) Does the following solution make sense? 1. During initialization, I'll get a random number generator from java.util.Random, initialized with the system time or something else that varies. 2. I'll give each person a field :rng, and will initialize each one with a sparate call to java.util.Random, with a seed determined by the RNG mentioned in the previous line. (After this I can let the inititial RNG to be garbage collected.) 3. During the steps in which each Person needs to sample from collections, the code will get the RNG from the Person's :rng file, and use it to determine what elements are sampled. There is more than one way that I could implement step 3. Here are some options I'm considering: (a) Bind data.generators/*rnd* to the RNG, and then call functions in data.generators. (b) Pass the Person's RNG to functions from bigml/sampling (which allow you to pass in an RNG). (c) Write my own sampling functions that use the RNG from the Person. Further remarks: When the application is single-threaded, each Person will use a different RNG, which isn't necessary, but it won't hurt, since the RNGs will have different seeds, except that I waste memory by creating multiple RNGs. When the application is multi-threaded, I still don't need one RNG per person, strictly speaking, since the number of threads will be much less than the number of Persons. However, giving each Person its own RNG is simpler. It means that my code can ignore threads and let Clojure figure out how to manage them. What do you think? Thanks in advance for any help. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [ANN] clj-generators - generator magic inspired by Python
Gary, I fully acknowledge that there are many ways to create lazy sequences that are much more elegant and efficient. However, as I mentioned, I'm very fascinated by generators in Python, and I mostly wanted to toy around with how to implement it in Clojure. Also, as I mentioned, for beginners who are not well-versed in Clojure laziness, it's easy to use generators in combination with the loop macro (or other more imperative macros) for a lazy but still functional-ish sequence. However, I'm probably not going to use this library for any of my own projects. :-) Thanks for the comments. --Alex On Wednesday, June 4, 2014 8:50:21 AM UTC-7, tbc++ wrote: A little known fact is that the guts of the go macro are quite flexible. We use this in the test framework: https://github.com/clojure/core.async/blob/master/src/test/clojure/clojure/core/async/ioc_macros_test.clj#L17 I also spent some time once and created a yield like macro: https://github.com/halgari/async-bench/blob/master/src/async_bench/core.clj#L64 WARNING: this uses unpublished APIs from core.async, use at your own risk. Timothy On Wed, Jun 4, 2014 at 9:43 AM, Gary Johnson gwjo...@uvm.edu javascript: wrote: What new features does this syntax provide over the existing infinite sequence generators? - lazy-seq - iterate - repeat - repeatedly - range I realize you provided a simple example for clarity, but perhaps you could illustrate something more complex that couldn't be done with the above functions easily. For example, the case you provided could be written as follows: (take 5 (iterate inc 1)) Thanks, ~Gary -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.com javascript: Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+u...@googlegroups.com javascript: For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com javascript:. For more options, visit https://groups.google.com/d/optout. -- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [ANN] clj-generators - generator magic inspired by Python
Gotcha. By all means then, hack away. ;-) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Advice on managing random number generators across threads
Thanks Lee. It looks like this could be useful. On Friday, June 6, 2014 4:19:11 PM UTC-5, Lee wrote: I don't know if this will be helpful in your application, or even if it's the best approach for our own work (or if java 1.7 provides a simpler approach?), but FWIW one of my projects deals with the thread-local RNG issue via: https://clojars.org/clj-random -Lee -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Advice on managing random number generators across threads
Wow. Linus, thanks for the very detailed answer. It sounds as your view is that there's no problem with the logic of my proposed solution, but it seems wasteful to create 100 RNGs, when I don't actually need to have so many of them. Your solutions provide ways to get the same result without maintaining so many RNG objects in a simulation run. Is that roughly correct? On Friday, June 6, 2014 2:26:25 PM UTC-5, Linus Ericsson wrote: (I think your stepwise problem is better to be solved without agents, see below.) I realized that the *rng* actually is conflated, it keeps both the state for the random number generator AND the algorithm used for the random number generation. This is usually not a problem, since the state-size and usage is dependent on the particular random number generator, but it becomes a problem when we need to separate and multithread things Interesting point. OK. But seem my comment below about sharing of code between RNG objects. One solution would be to either re-implement the algorithm (by Knuth) used in the original Sun Java random implementation, or use the experimental library Four [1] by Gary Fredericks that does exactly this. Four looks very nice. Its stateless RNGs return a new RNG, rather than an RNG state, btw: (class (rs/java-random 1001)) ;== four.stateless.JavaRandom (map class (rs/next-long (rs/java-random 1001))) ;== (java.lang.Long four.stateless.JavaRandom) I can see how this might be useful, though. What you would like to do is to be able to feed the rng-algorithm with the state (it is just a 64 bit long), and simply take the random-result generated from it, and store the state in the agent together with the rest of the simulation state. Dubious Speculations: This makes it necessary to know that the agents are called in the same order (if the influence on each other). Given the non-guarantee of ordering in the nature of Java Threads and how agents rely on them I don't think you can expect your result to be reproducible. Right. I can guarantee the order in which the random numbers are used when I use map to cause each person to do its work, but I assume that I can't guarantee this order when I use pmap. Here I assume that the incoming calls to agents aren't guaranteed to strictly ordered among different agents, even though the agents reside in one of two thread-pools (the send- vs. send-off pools). If two agents sent messages that arrived a third agent in different order, the rng-state would differ between the runs). Please correct me if I'm wrong on this one. No, there's no issue about the order in which messages are received, I believe. Communication is effectively simultaneous, because all sending happens in one step, and all receiving happens in another step. (Here are the details, if you're interested: Each Person random chooses other Persons to send a message to, and then randomly chooses a message to send. The pmap over the Persons ends, and all of the messages are collected into a single hashmap. Then a separate pmap goes through each Person, applying the messages in the hashmap that are supposed to be sent to that Person. Thus, although Persons perform their work in some order, the sending and the receiving of the messages are separated, so that message sending and receipt occurs as if all messages were sent simultaneously. In the next timestep, the messages received by a Person affect the probabilities that various messages will be chosen to send to another Person.) A possible clever way around this could be to send the rng state together with the message arriving at the agent, to make the agent at least react to the state in a similar way. Interesting idea. I don't think I'll need this, though. If you have some kind of continous magnitudes in the simulation - like pheromones - the simulation would maybe converge to similar results since the interaction effects would be reproducible but this is indeed a very far-fetched hypothesis. The simulation converges, but the same parameters can allow convergence to different outcomes. I usually have to run the simulation many times with the same parameters so that I can get a frequency distribution over outcomes. So only if your Person transform functions are commutative (ie gives the same result whichever order they was called in every timestep) the simulation could be reproducible by storing the local random generator seed in each Person. I see. I think I understand now. If I store the state and not the RNG code, but I am able to pass the state into the RNG code, that's all that I need to store in each Person. I think the idea is that this would do the same work as in my proposal, but with less storage. But wouldn't the RNG code be shared between RNG objects anyway? For example, don't all java.util.Random objects share the same code, differing only in that they
Re: Advice on managing random number generators across threads
On Friday, June 6, 2014 10:33:04 PM UTC-5, Mars0i wrote: On Friday, June 6, 2014 2:26:25 PM UTC-5, Linus Ericsson wrote: Here I assume that the incoming calls to agents aren't guaranteed to strictly ordered among different agents, even though the agents reside in one of two thread-pools (the send- vs. send-off pools). If two agents sent messages that arrived a third agent in different order, the rng-state would differ between the runs). Please correct me if I'm wrong on this one. No, there's no issue about the order in which messages are received, I believe. Communication is effectively simultaneous, because all sending happens in one step, and all receiving happens in another step. (Here are the details, if you're interested: Each Person random chooses other Persons to send a message to, and then randomly chooses a message to send. The pmap over the Persons ends, and all of the messages are collected into a single hashmap. Then a separate pmap goes through each Person, applying the messages in the hashmap that are supposed to be sent to that Person. Thus, although Persons perform their work in some order, the sending and the receiving of the messages are separated, so that message sending and receipt occurs as if all messages were sent simultaneously. In the next timestep, the messages received by a Person affect the probabilities that various messages will be chosen to send to another Person.) One more point about the detailed description: The immediate effects of messages on a Person who receives them are commutative (literally: they are additions). Nothing else happens until all of the immediate effects of all messages are applied. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [ANN] clj-generators - generator magic inspired by Python
What new features does this syntax provide over the existing infinite sequence generators? - lazy-seq - iterate - repeat - repeatedly - range I realize you provided a simple example for clarity, but perhaps you could illustrate something more complex that couldn't be done with the above functions easily. For example, the case you provided could be written as follows: (take 5 (iterate inc 1)) Thanks, ~Gary -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [ANN] clj-generators - generator magic inspired by Python
A little known fact is that the guts of the go macro are quite flexible. We use this in the test framework: https://github.com/clojure/core.async/blob/master/src/test/clojure/clojure/core/async/ioc_macros_test.clj#L17 I also spent some time once and created a yield like macro: https://github.com/halgari/async-bench/blob/master/src/async_bench/core.clj#L64 WARNING: this uses unpublished APIs from core.async, use at your own risk. Timothy On Wed, Jun 4, 2014 at 9:43 AM, Gary Johnson gwjoh...@uvm.edu wrote: What new features does this syntax provide over the existing infinite sequence generators? - lazy-seq - iterate - repeat - repeatedly - range I realize you provided a simple example for clarity, but perhaps you could illustrate something more complex that couldn't be done with the above functions easily. For example, the case you provided could be written as follows: (take 5 (iterate inc 1)) Thanks, ~Gary -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. -- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[ANN] clj-generators - generator magic inspired by Python
https://github.com/aengelberg/clj-generators My all-time favorite feature of Python is generators. It allows you to write lazy sequences imperatively. def infinite_range(): x = 1 while True: yield x x += 1 for i in infinite_range(): if (i 5): break else: print(i) = 1 2 3 4 5 This feature is so amazing and powerful, a common practice of mine is to ponder how to implement such magic in other languages. Python implements this feature using virtual stacks to suspend the computation in memory. Most languages don't have a similar way to pause a computation like that, short of manipulating entire threads, which gets messy quickly. However, when core.async came out for Clojure, I realized that the go-blocks can in fact pause in a lightweight way (because they park as they read/write), so it came to mind as a possible candidate for a Python generator implementation. The infinite_range example above would translate to the following Clojure code: (defn infinite-range [] (generator (loop [x 1] (yield x) (recur (inc x) (take 5 (infinite-range)) = (1 2 3 4 5) I realize this is a bit more imperative than most Clojure programmers would like. However, the addition of generators allows functional macros like loop to create lazy sequences (like in the example above), which it previously was unable to do. Check out the github site https://github.com/aengelberg/clj-generators for more details. It's relatively slow and inefficient but serves as a proof-of-concept. Enjoy! -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: generators...?
I'm fairly new to Clojure and this was a fun little exercise to try. (def color-map (reduce #(assoc % (count %) %2) {} [:red :yellow :blue :green :purple])) color-map = {4 :purple, 3 :green, 2 :blue, 1 :yellow, 0 :red} (defn random-repeating-map ([coll-map] (random-repeating-map coll-map coll-map)) ([coll-map new-coll-map] (if (seq new-coll-map) (let [ key-vec (into [] (keys new-coll-map)) idx-key (key-vec (rand-int (count key-vec)))] (cons (new-coll-map idx-key) (lazy-seq (random-repeating-map coll-map (dissoc new-coll-map idx-key) (random-repeating-map coll-map (take 20 (random-repeating-map color-map)) = (:blue :purple :yellow :red :green :purple :blue :red :yellow :green :red :purple :yellow :green :blue :green :blue :yellow :red :purple) Step 4: Profit On Wednesday, March 26, 2014 1:10:12 PM UTC-7, Gary Trakhman wrote: true, he did say 'or something that would be as useful', but lazy-seqs are more useful :-). On Wed, Mar 26, 2014 at 4:08 PM, Ben Wolfson wol...@gmail.comjavascript: wrote: cycle isn't really the same thing, though, at least if the OP really does require (for some reason) something that can be called repeatedly and get a different answer each time. On Wed, Mar 26, 2014 at 1:05 PM, Gary Trakhman gary.t...@gmail.comjavascript: wrote: cycle - http://clojuredocs.org/clojure_core/clojure.core/cycle And generally, this class of functionality is called lazy-seqs. On Wed, Mar 26, 2014 at 3:59 PM, Christopher Howard cmho...@alaska.edujavascript: wrote: Hi. I'm still fairly new to Clojure. I was wondering: What's the easiest way to make a generator (or something that would be as useful). In one application, I need something that will return a different color each time I call it - following a predefined list of colors, and starting over again at the beginning when colors are exhausted. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.comjavascript: Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+u...@googlegroups.com javascript: For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com javascript:. For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.comjavascript: Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+u...@googlegroups.com javascript: For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com javascript:. For more options, visit https://groups.google.com/d/optout. -- Ben Wolfson Human kind has used its intelligence to vary the flavour of drinks, which may be sweet, aromatic, fermented or spirit-based. ... Family and social life also offer numerous other occasions to consume drinks for pleasure. [Larousse, Drink entry] -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.comjavascript: Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+u...@googlegroups.com javascript: For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com javascript:. For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to
generators...?
Hi. I'm still fairly new to Clojure. I was wondering: What's the easiest way to make a generator (or something that would be as useful). In one application, I need something that will return a different color each time I call it - following a predefined list of colors, and starting over again at the beginning when colors are exhausted. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: generators...?
cycle - http://clojuredocs.org/clojure_core/clojure.core/cycle And generally, this class of functionality is called lazy-seqs. On Wed, Mar 26, 2014 at 3:59 PM, Christopher Howard cmhowa...@alaska.eduwrote: Hi. I'm still fairly new to Clojure. I was wondering: What's the easiest way to make a generator (or something that would be as useful). In one application, I need something that will return a different color each time I call it - following a predefined list of colors, and starting over again at the beginning when colors are exhausted. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: generators...?
If you really want something that can be called repeatedly and returns something different each time (rather than just iterating through an infinite sequence, which seems like it would be the more functional-ish approach): user (defn cycle-gen [input] (let [iter (atom (cycle input))] (fn [] (let [v (first @iter)] (swap! iter rest) v #'user/cycle-gen user (def colors (cycle-gen '(red green blue))) #'user/colors user (colors) red user (colors) green user (colors) blue user (colors) red user (colors) green user (colors) blue On Wed, Mar 26, 2014 at 12:59 PM, Christopher Howard cmhowa...@alaska.eduwrote: Hi. I'm still fairly new to Clojure. I was wondering: What's the easiest way to make a generator (or something that would be as useful). In one application, I need something that will return a different color each time I call it - following a predefined list of colors, and starting over again at the beginning when colors are exhausted. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. -- Ben Wolfson Human kind has used its intelligence to vary the flavour of drinks, which may be sweet, aromatic, fermented or spirit-based. ... Family and social life also offer numerous other occasions to consume drinks for pleasure. [Larousse, Drink entry] -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: generators...?
cycle isn't really the same thing, though, at least if the OP really does require (for some reason) something that can be called repeatedly and get a different answer each time. On Wed, Mar 26, 2014 at 1:05 PM, Gary Trakhman gary.trakh...@gmail.comwrote: cycle - http://clojuredocs.org/clojure_core/clojure.core/cycle And generally, this class of functionality is called lazy-seqs. On Wed, Mar 26, 2014 at 3:59 PM, Christopher Howard cmhowa...@alaska.eduwrote: Hi. I'm still fairly new to Clojure. I was wondering: What's the easiest way to make a generator (or something that would be as useful). In one application, I need something that will return a different color each time I call it - following a predefined list of colors, and starting over again at the beginning when colors are exhausted. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. -- Ben Wolfson Human kind has used its intelligence to vary the flavour of drinks, which may be sweet, aromatic, fermented or spirit-based. ... Family and social life also offer numerous other occasions to consume drinks for pleasure. [Larousse, Drink entry] -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: generators...?
true, he did say 'or something that would be as useful', but lazy-seqs are more useful :-). On Wed, Mar 26, 2014 at 4:08 PM, Ben Wolfson wolf...@gmail.com wrote: cycle isn't really the same thing, though, at least if the OP really does require (for some reason) something that can be called repeatedly and get a different answer each time. On Wed, Mar 26, 2014 at 1:05 PM, Gary Trakhman gary.trakh...@gmail.comwrote: cycle - http://clojuredocs.org/clojure_core/clojure.core/cycle And generally, this class of functionality is called lazy-seqs. On Wed, Mar 26, 2014 at 3:59 PM, Christopher Howard cmhowa...@alaska.edu wrote: Hi. I'm still fairly new to Clojure. I was wondering: What's the easiest way to make a generator (or something that would be as useful). In one application, I need something that will return a different color each time I call it - following a predefined list of colors, and starting over again at the beginning when colors are exhausted. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. -- Ben Wolfson Human kind has used its intelligence to vary the flavour of drinks, which may be sweet, aromatic, fermented or spirit-based. ... Family and social life also offer numerous other occasions to consume drinks for pleasure. [Larousse, Drink entry] -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
avoiding generators
I need to pull sequence ids from a db, which is a lot like using a generator. I found this thread about generators: https://groups.google.com/forum/?fromgroups=#!searchin/clojure/generator/clojure/IL_ONPb52-0/S_2p2-vjVCYJ which suggests using seqs, like so: (defn sines [] (cycle (map #(Math/sin %) (range 0 6.28 0.01 (doseq [s (take num-iters (sines))] (println s)) However my case is more complex, because there's not a single call (like doseq, above) consuming the seq. I'm processing structured data, and need to get ids for the leaf nodes. So it looks more like (defn process-row [row] (map #(process-value (get-id) %) row)) (map process-row rows) That is, process-row gets called multiple times, and needs to retrieve ids. If I pass in a seq of ids, I'll get the same ids each time. If I try to work around this by, say, have process-row return the number of ids consumed, and doing a drop n when calling process-row the next time, I'm holding the seq head (which I can't afford). Is there some other way to do this? -- -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.