Re: Transitive spec generation
In case anyone was wondering, it looks like this is probably a known issue: https://dev.clojure.org/jira/browse/CLJ-2079 On Wednesday, February 28, 2018 at 12:05:31 AM UTC-6, James Gatannah wrote: > > > > On Tuesday, February 27, 2018 at 12:45:26 AM UTC-6, Didier wrote: >> >> Don't fully understand what you are doing, >> > > (Slightly) bigger picture, I have a pair of functions that > serialize/deserialize maps where the values are mostly fixed-length byte > arrays. > > I want to verify that they round-trip correctly. > > This specific example is about two of those fields which really have the > same spec. I'm trying to define this in a way that's similar to a C typedef > (or possibly just something like using OOP inheritance for the sake of > documentation): > > (s/def ::extension ...) > (s/def ::server-extension ::extension) > (s/def ::client-extension ::extension) > > I'm doing this in an attempt to trying to reduce my nesting levels. > > This is what the weird subject is about: I'm trying to take advantage of > the transitive property of specs. > > > >> but when you run test.check, it seems to not always be generating random >> sample, it'll grow the samples. When you run sample, it'll always start >> back from the beginning. >> > >> You can see that by running: >> >> (sgen/sample (s/gen ::test) 100) >> >> See how the generated samples are getting longer and longer? >> > > Now instead try running this 10 times: > (sgen/sample (s/gen ::test) 10) > > And notice how you always get the same short samples? > > > > (I'm sorry about the quote mangling). > > Since I have to have a specific length, I'm specifying that as a parameter > to sgen/vector. > > This part of it works. I can run s/sample on my generator and validate its > output against the spec without any trouble. > > Actually, if I define the ::extension spec using with-gen, it also looks > as though it works (I just ran across this, so haven't tested it > thoroughly). But then my library has a runtime dependency on test.check. > That's not the end of the world, but it's a definite downside. > > I haven't been able to find real documentation covering the arguments to > s/gen. But it looks as though I can pass in a map of 0-arity functions to > override the different generators. The keys to that map override specs > being generated. I can't remember now where I found this, but it can't be > totally undocumented. I haven't studied the source code thoroughly enough > to have picked out that sort of detail. > > So: > > (s/gen (s/keys :req [::server-extension > ::client-extension]) >{::server-extension #(gen/fmap byte-array (gen/vector (gen/choose > -128 127) extension-length)) > ::client-extension #(gen/fmap byte-array (gen/vector (gen/choose > -128 127) extension-length))}) > > > calls the function in the value associated with each key to override the > generator for that spec. > > This is the part that seems to only work sometimes. > > When I extend this to include all the keys in the full spec, these are the > only two that have problems. They're also the only ones that are directly > defined as another spec definition. (Which is why I'm pointing my finger at > my attempt to use the "transitive" property, though that could totally be a > red herring). > > When I run this inside deftest, it seems fine. Really, that's all I need. > But I'd really like to understand the seemingly non-deterministic failures. > > I wrote a function called manual-check that takes that generator and calls > sgen/sample on it. > > When I call that function directly from the REPL, it very nearly always > fails. > > When I call it 40 times in a reduce inside deftest, I haven't seen it fail > yet. > > * While I was writing this, I stumbled across another piece that seems > like an interesting clue: > > If I override the generator for ::extension rather than the individual > specs that I've defined transitively, it seems to start working. > > i.e. > > (s/gen (s/keys :req [::server-extension > ::client-extension]) >{::extension #(gen/fmap byte-array (gen/vector (gen/choose -128 > 127) extension-length))}) > > seems to work. > > It's still less than ideal, in case I ever want to change the underlying > spec that's the "base" definition, since I'll have to remember to change > the base generator. But I really shouldn't have this sort of thing > scattered around everywhere. Especially since it's most interesting inside > deftest anyway, where both appr
Re: Transitive spec generation
On Tuesday, February 27, 2018 at 12:45:26 AM UTC-6, Didier wrote: > > Don't fully understand what you are doing, > (Slightly) bigger picture, I have a pair of functions that serialize/deserialize maps where the values are mostly fixed-length byte arrays. I want to verify that they round-trip correctly. This specific example is about two of those fields which really have the same spec. I'm trying to define this in a way that's similar to a C typedef (or possibly just something like using OOP inheritance for the sake of documentation): (s/def ::extension ...) (s/def ::server-extension ::extension) (s/def ::client-extension ::extension) I'm doing this in an attempt to trying to reduce my nesting levels. This is what the weird subject is about: I'm trying to take advantage of the transitive property of specs. > but when you run test.check, it seems to not always be generating random > sample, it'll grow the samples. When you run sample, it'll always start > back from the beginning. > > You can see that by running: > > (sgen/sample (s/gen ::test) 100) > > See how the generated samples are getting longer and longer? > Now instead try running this 10 times: (sgen/sample (s/gen ::test) 10) And notice how you always get the same short samples? (I'm sorry about the quote mangling). Since I have to have a specific length, I'm specifying that as a parameter to sgen/vector. This part of it works. I can run s/sample on my generator and validate its output against the spec without any trouble. Actually, if I define the ::extension spec using with-gen, it also looks as though it works (I just ran across this, so haven't tested it thoroughly). But then my library has a runtime dependency on test.check. That's not the end of the world, but it's a definite downside. I haven't been able to find real documentation covering the arguments to s/gen. But it looks as though I can pass in a map of 0-arity functions to override the different generators. The keys to that map override specs being generated. I can't remember now where I found this, but it can't be totally undocumented. I haven't studied the source code thoroughly enough to have picked out that sort of detail. So: (s/gen (s/keys :req [::server-extension ::client-extension]) {::server-extension #(gen/fmap byte-array (gen/vector (gen/choose -128 127) extension-length)) ::client-extension #(gen/fmap byte-array (gen/vector (gen/choose -128 127) extension-length))}) calls the function in the value associated with each key to override the generator for that spec. This is the part that seems to only work sometimes. When I extend this to include all the keys in the full spec, these are the only two that have problems. They're also the only ones that are directly defined as another spec definition. (Which is why I'm pointing my finger at my attempt to use the "transitive" property, though that could totally be a red herring). When I run this inside deftest, it seems fine. Really, that's all I need. But I'd really like to understand the seemingly non-deterministic failures. I wrote a function called manual-check that takes that generator and calls sgen/sample on it. When I call that function directly from the REPL, it very nearly always fails. When I call it 40 times in a reduce inside deftest, I haven't seen it fail yet. * While I was writing this, I stumbled across another piece that seems like an interesting clue: If I override the generator for ::extension rather than the individual specs that I've defined transitively, it seems to start working. i.e. (s/gen (s/keys :req [::server-extension ::client-extension]) {::extension #(gen/fmap byte-array (gen/vector (gen/choose -128 127) extension-length))}) seems to work. It's still less than ideal, in case I ever want to change the underlying spec that's the "base" definition, since I'll have to remember to change the base generator. But I really shouldn't have this sort of thing scattered around everywhere. Especially since it's most interesting inside deftest anyway, where both approaches always seem to work (I haven't tested this out thoroughly yet either). My current hypothesis is that there's something about the deftest macro that interacts with test.check in a way that makes gen more capable in terms of resolving which spec I actually mean/want to override. I know (based on digging through internals) that it calls something (I think it's named specize) that resolves the spec's name. Then it has to use that name/those names in the overriding map parameter to pick out the appropriate function to call to get the generator. I'm very skeptical, but could that possibly hold water? Thank you to anyone who actually took the time to read this! > > > On Monday, 26 February 2018 21:39:09 UTC-8, James Ga
Re: Transitive spec generation
Don't fully understand what you are doing, but when you run test.check, it seems to not always be generating random sample, it'll grow the samples. When you run sample, it'll always start back from the beginning. You can see that by running: (sgen/sample (s/gen ::test) 100) See how the generated samples are getting longer and longer? Now instead try running this 10 times: (sgen/sample (s/gen ::test) 10) And notice how you always get the same short samples? On Monday, 26 February 2018 21:39:09 UTC-8, James Gatannah wrote: > > Fairly minimalist example available at > https://gist.github.com/jimrthy/21851c52a8cd6b04a31ed08b1d0a7f04 > > When I call gen/sample from inside a unit test, it seems to pass with > flying colors. > > When I directly eval the gen/sample form or call (manual-check) from the > REPL (I checked both CIDER and the boot CLI, just in case), I usually get > the "Couldn't satisfy such-that predicate after 100 tries." > > To be a little more specific about this: > > Calling (manual-check) failed 49/50 times. > > Calling (transitive-indirect) passed 50 times in a row. If you haven't > bothered looking at the gist, each of those calls (manual-check) 40 times. > > I was quite surprised by this. Does anyone have any suggestions about why > wrapping the call in a unit test might help it succeed more often? > > If I just call gen/sample on the generator I'm trying to use, followed by > s/valid? for one of the specs I'm trying to generate, it seems fine. I > haven't dug into the source here (and I'm not positive what all's going on > inside the spec.gen namespace), but I thought that's what gen/generate does > when you define a custom generator for your spec. > > Except that isn't really what I'm doing. > > I'm trying to avoid adding extra runtime dependencies on a library like > tools.check, so I'm trying to do this with overrides in the test namespaces > to try to limit the extra dependencies to test time. > > Could that be where I'm breaking core assumptions that don't seem to cause > trouble for anyone else? > > Thanks, > James > > > > On Sunday, February 25, 2018 at 6:45:39 PM UTC-6, James Gatannah wrote: >> >> I have a spec for an array of 16 bytes: >> >> (s/def ::extension (s/and bytes? >>#(= (count %) 16)) >> >> Then I have a couple of other specs that are really just renaming it: >> >> (s/def ::client-extension ::extension) >> (s/def ::server-extension ::extension) >> >> I started doing some refactoring today, and the definitions wound up >> needing to move to a different namespace. >> >> So now the original definitions have changed to >> >> (s/def ::client-extension ::refactored/client-extension) >> >> I also started dabbling with generators, and came up with this: >> >> (gen/generate (s/gen ::client-extension >> {::client-extension #(gen/fmap >> byte-array (gen/vector (gen/choose -128 127) 16)})) >> >> When I define things this way, I get a "Couldn't satisfy such-that >> predicate after 100 tries." exception a little more than half the time. >> >> If I rearrange things so that either >> a) The refactored namespace defines the spec directly >> or >> b) I change my generator override to specify the top-level spec that the >> others are copying >> >> i.e. >> a) would mean changing the refactored ns such that I have >> (s/def ::client-extension (s/and bytes? >> #(= (count %) 16)) >> >> b) changing the generator to >> (gen/generate (s/gen ::client-extension >> {::refactored/extension #(gen/fmap >> byte-array (gen/vector (gen/choose -128 127) 16)})) >> >> it seems to fail (with the same problem) about 1 time in 5. >> >> I haven't seen it fail yet if I undo my refactoring and move the spec >> back to the original location. >> >> I haven't collected any sorts of real numbers on this, much less tried to >> make enough test runs to collect a statistically significant sample. I know >> the next real steps are to put together a minimalist example. >> >> But before I do that, I figured it might be asking whether anyone sees >> anything obviously wrong in what I'm trying to do, or whether there's a >> better way to do it. >> >> Thanks in advance, >> James >> >> -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googl
Re: Transitive spec generation
Fairly minimalist example available at https://gist.github.com/jimrthy/21851c52a8cd6b04a31ed08b1d0a7f04 When I call gen/sample from inside a unit test, it seems to pass with flying colors. When I directly eval the gen/sample form or call (manual-check) from the REPL (I checked both CIDER and the boot CLI, just in case), I usually get the "Couldn't satisfy such-that predicate after 100 tries." To be a little more specific about this: Calling (manual-check) failed 49/50 times. Calling (transitive-indirect) passed 50 times in a row. If you haven't bothered looking at the gist, each of those calls (manual-check) 40 times. I was quite surprised by this. Does anyone have any suggestions about why wrapping the call in a unit test might help it succeed more often? If I just call gen/sample on the generator I'm trying to use, followed by s/valid? for one of the specs I'm trying to generate, it seems fine. I haven't dug into the source here (and I'm not positive what all's going on inside the spec.gen namespace), but I thought that's what gen/generate does when you define a custom generator for your spec. Except that isn't really what I'm doing. I'm trying to avoid adding extra runtime dependencies on a library like tools.check, so I'm trying to do this with overrides in the test namespaces to try to limit the extra dependencies to test time. Could that be where I'm breaking core assumptions that don't seem to cause trouble for anyone else? Thanks, James On Sunday, February 25, 2018 at 6:45:39 PM UTC-6, James Gatannah wrote: > > I have a spec for an array of 16 bytes: > > (s/def ::extension (s/and bytes? >#(= (count %) 16)) > > Then I have a couple of other specs that are really just renaming it: > > (s/def ::client-extension ::extension) > (s/def ::server-extension ::extension) > > I started doing some refactoring today, and the definitions wound up > needing to move to a different namespace. > > So now the original definitions have changed to > > (s/def ::client-extension ::refactored/client-extension) > > I also started dabbling with generators, and came up with this: > > (gen/generate (s/gen ::client-extension > {::client-extension #(gen/fmap > byte-array (gen/vector (gen/choose -128 127) 16)})) > > When I define things this way, I get a "Couldn't satisfy such-that > predicate after 100 tries." exception a little more than half the time. > > If I rearrange things so that either > a) The refactored namespace defines the spec directly > or > b) I change my generator override to specify the top-level spec that the > others are copying > > i.e. > a) would mean changing the refactored ns such that I have > (s/def ::client-extension (s/and bytes? > #(= (count %) 16)) > > b) changing the generator to > (gen/generate (s/gen ::client-extension > {::refactored/extension #(gen/fmap > byte-array (gen/vector (gen/choose -128 127) 16)})) > > it seems to fail (with the same problem) about 1 time in 5. > > I haven't seen it fail yet if I undo my refactoring and move the spec back > to the original location. > > I haven't collected any sorts of real numbers on this, much less tried to > make enough test runs to collect a statistically significant sample. I know > the next real steps are to put together a minimalist example. > > But before I do that, I figured it might be asking whether anyone sees > anything obviously wrong in what I'm trying to do, or whether there's a > better way to do it. > > Thanks in advance, > James > > -- 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.
Transitive spec generation
I have a spec for an array of 16 bytes: (s/def ::extension (s/and bytes? #(= (count %) 16)) Then I have a couple of other specs that are really just renaming it: (s/def ::client-extension ::extension) (s/def ::server-extension ::extension) I started doing some refactoring today, and the definitions wound up needing to move to a different namespace. So now the original definitions have changed to (s/def ::client-extension ::refactored/client-extension) I also started dabbling with generators, and came up with this: (gen/generate (s/gen ::client-extension {::client-extension #(gen/fmap byte-array (gen/vector (gen/choose -128 127) 16)})) When I define things this way, I get a "Couldn't satisfy such-that predicate after 100 tries." exception a little more than half the time. If I rearrange things so that either a) The refactored namespace defines the spec directly or b) I change my generator override to specify the top-level spec that the others are copying i.e. a) would mean changing the refactored ns such that I have (s/def ::client-extension (s/and bytes? #(= (count %) 16)) b) changing the generator to (gen/generate (s/gen ::client-extension {::refactored/extension #(gen/fmap byte-array (gen/vector (gen/choose -128 127) 16)})) it seems to fail (with the same problem) about 1 time in 5. I haven't seen it fail yet if I undo my refactoring and move the spec back to the original location. I haven't collected any sorts of real numbers on this, much less tried to make enough test runs to collect a statistically significant sample. I know the next real steps are to put together a minimalist example. But before I do that, I figured it might be asking whether anyone sees anything obviously wrong in what I'm trying to do, or whether there's a better way to do it. Thanks in advance, James -- 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: :npm-deps and transitive dependencies
You can create a deps.cljs in the root of your classpath for Y and declare :npm-deps there ;; src/deps.cljs {:npm-deps {"the-thing" "version"}} This way the compiler can pick up your npm dependency and install it. On Monday, January 15, 2018 at 9:01:55 AM UTC+1, Lucas Wiener wrote: > > Hi, > > I have the following clojurescript project dependency setup: X -> Y (X has > stated Y in :dependencies). Now, I would like Y to depend on a npm > javascript library Z. Following the guides, I added :npm-deps to one of the > builds specified in Y. When I build and run Y, everything works fine with > the new Z dependency. However, building/running project X now fails since > the dependency Z cannot be found. From what I currently know, there are two > approaches to get X running again: > > 1) Specify Z as an :npm-deps also in the project X builds. This is not > very elegant since the union of all dependencies now cascade to the top > level projects. Also, this approach would fail when transitive dependencies > need different versions of the same dependency. > 2) Compile Y into a bundle. Then X would depend on the prebuilt bundle of > Y (which already includes Z). This is not perfect since it requires an > extra processing step in Y, making lein checkouts a bit more troublesome > etc. Also, my intuition tells me that this might affect code splitting, > compilation optimizations, dead code elimination, etc. in a negative way. > > Am I missing something? > -- 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: :npm-deps and transitive dependencies
I now realise that this question might belong to the ClojureScript group, so I'm posting it there as well. Feel free to remove this thread if you want. Den måndag 15 januari 2018 kl. 09:01:55 UTC+1 skrev Lucas Wiener: > > Hi, > > I have the following clojurescript project dependency setup: X -> Y (X has > stated Y in :dependencies). Now, I would like Y to depend on a npm > javascript library Z. Following the guides, I added :npm-deps to one of the > builds specified in Y. When I build and run Y, everything works fine with > the new Z dependency. However, building/running project X now fails since > the dependency Z cannot be found. From what I currently know, there are two > approaches to get X running again: > > 1) Specify Z as an :npm-deps also in the project X builds. This is not > very elegant since the union of all dependencies now cascade to the top > level projects. Also, this approach would fail when transitive dependencies > need different versions of the same dependency. > 2) Compile Y into a bundle. Then X would depend on the prebuilt bundle of > Y (which already includes Z). This is not perfect since it requires an > extra processing step in Y, making lein checkouts a bit more troublesome > etc. Also, my intuition tells me that this might affect code splitting, > compilation optimizations, dead code elimination, etc. in a negative way. > > Am I missing something? > -- 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.
:npm-deps and transitive dependencies
Hi, I have the following clojurescript project dependency setup: X -> Y (X has stated Y in :dependencies). Now, I would like Y to depend on a npm javascript library Z. Following the guides, I added :npm-deps to one of the builds specified in Y. When I build and run Y, everything works fine with the new Z dependency. However, building/running project X now fails since the dependency Z cannot be found. From what I currently know, there are two approaches to get X running again: 1) Specify Z as an :npm-deps also in the project X builds. This is not very elegant since the union of all dependencies now cascade to the top level projects. Also, this approach would fail when transitive dependencies need different versions of the same dependency. 2) Compile Y into a bundle. Then X would depend on the prebuilt bundle of Y (which already includes Z). This is not perfect since it requires an extra processing step in Y, making lein checkouts a bit more troublesome etc. Also, my intuition tells me that this might affect code splitting, compilation optimizations, dead code elimination, etc. in a negative way. Am I missing something? -- 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 CLI tool fails to resolve weird transitive dependencies.
Yep, that looks like what I'm seeing. 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: Clojure CLI tool fails to resolve weird transitive dependencies.
Hm, looks like this is an open issue: https://dev.clojure.org/jira/browse/TDEPS-12 -- David -- 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 CLI tool fails to resolve weird transitive dependencies.
Ha, I think that must’ve snuck in there during editing. Fixing that particular typo didn’t help any. :D > On Dec 11, 2017, at 12:22 PM, David Bürginwrote: > > On 11/12/17 20:47, Jonathan Fischer wrote: >> com.badlogicgames.gdx/gdx {:mvn/versin "1.9.6"} > > Typo? > > > -- > David > > -- > 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 a topic in the Google > Groups "Clojure" group. > To unsubscribe from this topic, visit > https://groups.google.com/d/topic/clojure/t_DA1T36VKQ/unsubscribe. > To unsubscribe from this group and all its topics, 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: Clojure CLI tool fails to resolve weird transitive dependencies.
On 11/12/17 20:47, Jonathan Fischer wrote: > com.badlogicgames.gdx/gdx {:mvn/versin "1.9.6"} Typo? -- David -- 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 CLI tool fails to resolve weird transitive dependencies.
I apologize, I'm not certain of the right name for this. I'm pulling in libgdx and its dependencies. In Leiningen, my dependencies vector looks like this: :dependencies [[org.clojure/clojure "1.8.0"] [com.badlogicgames.gdx/gdx "1.9.6"] [com.badlogicgames.gdx/gdx-backend-lwjgl3 "1.9.6"] [com.badlogicgames.gdx/gdx-platform "1.9.6" :classifier "natives-desktop"]] Which expands out to this (in lein deps :tree, leaving out the Clojure core libs and nrepl and whatnot): [com.badlogicgames.gdx/gdx-backend-lwjgl3 "1.9.6"] [com.badlogicgames.jlayer/jlayer "1.0.1-gdx"] [org.jcraft/jorbis "0.0.17"] [org.lwjgl/lwjgl-glfw "3.1.0"] [org.lwjgl/lwjgl-glfw "3.1.0" :classifier "natives-linux"] [org.lwjgl/lwjgl-glfw "3.1.0" :classifier "natives-macos"] [org.lwjgl/lwjgl-glfw "3.1.0" :classifier "natives-windows"] [org.lwjgl/lwjgl-jemalloc "3.1.0"] [org.lwjgl/lwjgl-jemalloc "3.1.0" :classifier "natives-linux"] [org.lwjgl/lwjgl-jemalloc "3.1.0" :classifier "natives-macos"] [org.lwjgl/lwjgl-jemalloc "3.1.0" :classifier "natives-windows"] [org.lwjgl/lwjgl-openal "3.1.0"] [org.lwjgl/lwjgl-openal "3.1.0" :classifier "natives-linux"] [org.lwjgl/lwjgl-openal "3.1.0" :classifier "natives-macos"] [org.lwjgl/lwjgl-openal "3.1.0" :classifier "natives-windows"] [org.lwjgl/lwjgl-opengl "3.1.0"] [org.lwjgl/lwjgl "3.1.0"] [org.lwjgl/lwjgl "3.1.0" :classifier "natives-linux"] [org.lwjgl/lwjgl "3.1.0" :classifier "natives-macos"] [org.lwjgl/lwjgl "3.1.0" :classifier "natives-windows"] [com.badlogicgames.gdx/gdx-platform "1.9.6" :classifier "natives-desktop"] [com.badlogicgames.gdx/gdx "1.9.6"] And the classpath ends up like this: /Users/jfischer/Desktop/Clojure/gdx-skeleton/test:/Users/jfischer/Desktop/Clojure/gdx-skeleton/src:/Users/jfischer/Desktop/Clojure/gdx-skeleton/dev-resources:/Users/jfischer/Desktop/Clojure/gdx-skeleton/resources:/Users/jfischer/Desktop/Clojure/gdx-skeleton/target/default/classes:/Users/jfischer/.m2/repository/org/clojure/clojure/1.8.0/clojure-1.8.0.jar:/Users/jfischer/.m2/repository/com/badlogicgames/gdx/gdx-backend-lwjgl3/1.9.6/gdx-backend-lwjgl3-1.9.6.jar:/Users/jfischer/.m2/repository/org/lwjgl/lwjgl-openal/3.1.0/lwjgl-openal-3.1.0.jar:/Users/jfischer/.m2/repository/org/lwjgl/lwjgl-openal/3.1.0/lwjgl-openal-3.1.0-natives-windows.jar:/Users/jfischer/.m2/repository/org/lwjgl/lwjgl/3.1.0/lwjgl-3.1.0.jar:/Users/jfischer/.m2/repository/com/badlogicgames/gdx/gdx/1.9.6/gdx-1.9.6.jar:/Users/jfischer/.m2/repository/org/jcraft/jorbis/0.0.17/jorbis-0.0.17.jar:/Users/jfischer/.m2/repository/org/lwjgl/lwjgl-openal/3.1.0/lwjgl-openal-3.1.0-natives-macos.jar:/Users/jfischer/.m2/repository/cider/cider-nrepl/0.15.0/cider-nrepl-0.15.0.jar:/Users/jfischer/.m2/repository/com/badlogicgames/gdx/gdx-platform/1.9.6/gdx-platform-1.9.6-natives-desktop.jar:/Users/jfischer/.m2/repository/org/lwjgl/lwjgl-glfw/3.1.0/lwjgl-glfw-3.1.0.jar:/Users/jfischer/.m2/repository/clojure-complete/clojure-complete/0.2.4/clojure-complete-0.2.4.jar:/Users/jfischer/.m2/repository/org/lwjgl/lwjgl-glfw/3.1.0/lwjgl-glfw-3.1.0-natives-macos.jar:/Users/jfischer/.m2/repository/org/lwjgl/lwjgl-glfw/3.1.0/lwjgl-glfw-3.1.0-natives-windows.jar:/Users/jfischer/.m2/repository/org/lwjgl/lwjgl-opengl/3.1.0/lwjgl-opengl-3.1.0.jar:/Users/jfischer/.m2/repository/org/lwjgl/lwjgl/3.1.0/lwjgl-3.1.0-natives-windows.jar:/Users/jfischer/.m2/repository/org/lwjgl/lwjgl/3.1.0/lwjgl-3.1.0-natives-linux.jar:/Users/jfischer/.m2/repository/org/lwjgl/lwjgl-jemalloc/3.1.0/lwjgl-jemalloc-3.1.0.jar:/Users/jfischer/.m2/repository/org/lwjgl/lwjgl-jemalloc/3.1.0/lwjgl-jemalloc-3.1.0-natives-windows.jar:/Users/jfischer/.m2/repository/com/badlogicgames/jlayer/jlayer/1.0.1-gdx/jlayer-1.0.1-gdx.jar:/Users/jfischer/.m2/repository/org/tcrawley/dynapath/0.2.5/dynapath-0.2.5.jar:/Users/jfischer/.m2/repository/org/lwjgl/lwjgl-glfw/3.1.0/lwjgl-glfw-3.1.0-natives-linux.jar:/Users/jfischer/.m2/repository/org/lwjgl/lwjgl/3.1.0/lwjgl-3.1.0-natives-macos.jar:/Users/jfischer/.m2/repository/org/lwjgl/lwjgl-jemalloc/3.1.0/lwjgl-jemalloc-3.1.0-natives-linux.jar:/Users/jfischer/.m2/repository/org/clojure/tools.nrepl/0.2.12/tools.nrepl-0.2.12.jar:/Users/jfischer/.m2/repository/org/lwjgl/lwjgl-openal/3.1.0/lwjgl-openal-3.1.0-natives-linux.jar:/Users/jfischer/.m2/repository/org/lwjgl/lwjgl-jemalloc/3.1.0/lwjgl-jemalloc-3.1.0-natives-macos.jar Importantly, there's a jar there for each of those classifiers. If I try and replicate the same thing using deps.edn: {:deps {org.clojure/clojure {:mvn/version "1.8.0"} com.badlogicgames.gdx/gdx {:mvn/versin "1.9.6"} com.badlogicgames.gdx/gdx-backend-lwjgl3 {:mvn/version "1.9.6"} com.badlogicgames.gdx/gdx-platform {:mvn/version "1.9.6" :classifier "natives-desktop"}}} I don't get all of the jars with different classifiers:
core.logic - explaining transitive relationships
Hello, With the code below you can query transitive relationships between entities successfully. Is there any way to use core.logic explain the relationship? Specifically, is there any way to write a function explain so that: (explain :pitbull :chordate) will give you: [:pitbull :dog] [:dog :mammal] [:mammal :chordate] Thanks, Stathis Code: (ns test.logic (:refer-clojure :exclude [==]) (:use clojure.core.logic)) (defrel is-a Entity Parent) (fact is-a :pitbull :dog) (fact is-a :dog :mammal) (fact is-a :mammal :chordate) (fact is-a :chordate :animal) (defn transitive [r] (fn t [p1 p2] (fresh [intermediate] (conde ((r p1 p2)) ((r p1 intermediate) (t intermediate p2)) (defn iso [entity parent] ((transitive is-a) entity parent)) In the REPL: (run* [q] (iso :dog :animal)) (_.0) -- 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
Re: core.logic - explaining transitive relationships
Stathis Sideris side...@gmail.com writes: Hi Stathis, With the code below you can query transitive relationships between entities successfully. Is there any way to use core.logic explain the relationship? Specifically, is there any way to write a function explain so that: (explain :pitbull :chordate) will give you: [:pitbull :dog] [:dog :mammal] [:mammal :chordate] Can't you define `iso` with 3 args, one being a list of intermediates? E.g., something like (defn iso [entity is parent] (conde [(is-a entity parent) (== is ())] [(fresh [i nis] (is-a entity i) (conso i nis is) (iso i nis parent))])) Then you could run it like: test.logic (run* [q] (iso :pitbull q :animal)) ((:dog :mammal :chordate)) Bye, Tassilo -- 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
Re: core.logic - explaining transitive relationships
Hello David, Yes, I wasn't expecting for this to be built-in. Your example is exactly what I was looking for, thanks a lot! I'll to need to spend some time to figure it out :-) Stathis On Tuesday, 18 December 2012 15:52:47 UTC, David Nolen wrote: There is no general explain functionality. However the following simple solution should give you some ideas: (defrel is-a Entity Parent) (fact is-a :pitbull :dog) (fact is-a :dog :mammal) (fact is-a :mammal :chordate) (fact is-a :chordate :animal) (defn transitive [r] (fn t ([x z] (t x z (lvar))) ([x z path] (fresh [y] (conde [(r x z) (== path '())] [(fresh [a d] (r x y) (conso a d path) (== a [x y]) (t y z d))]) (defn iso ([entity parent] ((transitive is-a) entity parent)) ([entity parent path] ((transitive is-a) entity parent path))) (comment (run* [q] (iso :dog :animal q)) ) On Tue, Dec 18, 2012 at 9:06 AM, Stathis Sideris sid...@gmail.comjavascript: wrote: Hello, With the code below you can query transitive relationships between entities successfully. Is there any way to use core.logic explain the relationship? Specifically, is there any way to write a function explain so that: (explain :pitbull :chordate) will give you: [:pitbull :dog] [:dog :mammal] [:mammal :chordate] Thanks, Stathis Code: (ns test.logic (:refer-clojure :exclude [==]) (:use clojure.core.logic)) (defrel is-a Entity Parent) (fact is-a :pitbull :dog) (fact is-a :dog :mammal) (fact is-a :mammal :chordate) (fact is-a :chordate :animal) (defn transitive [r] (fn t [p1 p2] (fresh [intermediate] (conde ((r p1 p2)) ((r p1 intermediate) (t intermediate p2)) (defn iso [entity parent] ((transitive is-a) entity parent)) In the REPL: (run* [q] (iso :dog :animal)) (_.0) -- 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 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
Re: core.logic - explaining transitive relationships
Thanks for this. I didn't think about that! On Tuesday, 18 December 2012 15:51:55 UTC, Tassilo Horn wrote: Stathis Sideris sid...@gmail.com javascript: writes: Hi Stathis, With the code below you can query transitive relationships between entities successfully. Is there any way to use core.logic explain the relationship? Specifically, is there any way to write a function explain so that: (explain :pitbull :chordate) will give you: [:pitbull :dog] [:dog :mammal] [:mammal :chordate] Can't you define `iso` with 3 args, one being a list of intermediates? E.g., something like (defn iso [entity is parent] (conde [(is-a entity parent) (== is ())] [(fresh [i nis] (is-a entity i) (conso i nis is) (iso i nis parent))])) Then you could run it like: test.logic (run* [q] (iso :pitbull q :animal)) ((:dog :mammal :chordate)) Bye, Tassilo -- 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
Re: core.logic - explaining transitive relationships
;; there is a transitive relationship between x z if there is a ;; relationship between x some y and some y z (defn transitive [r] (fn t ;; if passed only two args create the path logic var ([x z] (t x z (lvar))) ;; take an x, z, and a path from x to z ([x z path] (fresh [y] (conde ;; there is a direct relationship between x z ;; update the path [(r x z) (== path (list [x z]))] ;; there is not a direct relationship between x z ;; try some y that has a relationship with x, update the path [(fresh [a d] (r x y) (conso a d path) (== a [x y]) ;; prove there is a relationship between y z (t y z d))]) (defn iso ([entity parent] ((transitive is-a) entity parent)) ([entity parent path] ((transitive is-a) entity parent path))) On Tue, Dec 18, 2012 at 11:28 AM, Stathis Sideris side...@gmail.com wrote: Hello David, Yes, I wasn't expecting for this to be built-in. Your example is exactly what I was looking for, thanks a lot! I'll to need to spend some time to figure it out :-) Stathis On Tuesday, 18 December 2012 15:52:47 UTC, David Nolen wrote: There is no general explain functionality. However the following simple solution should give you some ideas: (defrel is-a Entity Parent) (fact is-a :pitbull :dog) (fact is-a :dog :mammal) (fact is-a :mammal :chordate) (fact is-a :chordate :animal) (defn transitive [r] (fn t ([x z] (t x z (lvar))) ([x z path] (fresh [y] (conde [(r x z) (== path '())] [(fresh [a d] (r x y) (conso a d path) (== a [x y]) (t y z d))]) (defn iso ([entity parent] ((transitive is-a) entity parent)) ([entity parent path] ((transitive is-a) entity parent path))) (comment (run* [q] (iso :dog :animal q)) ) On Tue, Dec 18, 2012 at 9:06 AM, Stathis Sideris sid...@gmail.comwrote: Hello, With the code below you can query transitive relationships between entities successfully. Is there any way to use core.logic explain the relationship? Specifically, is there any way to write a function explain so that: (explain :pitbull :chordate) will give you: [:pitbull :dog] [:dog :mammal] [:mammal :chordate] Thanks, Stathis Code: (ns test.logic (:refer-clojure :exclude [==]) (:use clojure.core.logic)) (defrel is-a Entity Parent) (fact is-a :pitbull :dog) (fact is-a :dog :mammal) (fact is-a :mammal :chordate) (fact is-a :chordate :animal) (defn transitive [r] (fn t [p1 p2] (fresh [intermediate] (conde ((r p1 p2)) ((r p1 intermediate) (t intermediate p2)) (defn iso [entity parent] ((transitive is-a) entity parent)) In the REPL: (run* [q] (iso :dog :animal)) (_.0) -- 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 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 For more options, visit this group at http://groups.google.com/**group/clojure?hl=enhttp://groups.google.com/group/clojure?hl=en -- 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 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
Re: == is not transitive?
On Friday, October 5, 2012 7:17:50 PM UTC+2, Ben wrote: I'm not sure what you mean by this. Transitivity means that for all x, y, and z, (Fxy Fyz) = Fxz. But there are values of x, y, and z for which that does not hold. Yeah, sorry. What I meant was that == is only commutative if you pass it two arguments as of right now. -- 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
Re: == is not transitive?
On Friday, October 5, 2012 2:39:05 AM UTC+2, Ben wrote: user [(== 0 0.0) (== 0.0 0.0M) (== 0.0M 0)] [true true false] When passing two arguments to ==, == will be transitive. user [(== 0 0.0 0.0M) (== 0 0.0M 0.0) (== 0.0 0 0.0M) (== 0.0 0.0M 0) (== 0.0M 0.0 0) (== 0.0M 0 0.0)] [true false false false true false] This is more of a problem with number equality, not the transitivity of ==. (== x1 x2 x3 ... xn) can be rewritten as (and (== x1 x2) (== x2 x3) ... (== xn-1 xn)). So if you compare (== x y z), then if x = y, then the result of (== x z) and (== y z) should be equivalent, considering the numbers are, well, numbers. I believe the issue lies within the bigdec-parsing, which seems to have two zeroes: (== 0M 0.0M) returns false, and their hashcode (0 and 1, respectively) are different. -- 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
Re: == is not transitive?
On Fri, Oct 5, 2012 at 11:08 AM, Jean Niklas L'orange jeann...@hypirion.com wrote: On Friday, October 5, 2012 2:39:05 AM UTC+2, Ben wrote: user [(== 0 0.0) (== 0.0 0.0M) (== 0.0M 0)] [true true false] When passing two arguments to ==, == will be transitive. user [(== 0 0.0 0.0M) (== 0 0.0M 0.0) (== 0.0 0 0.0M) (== 0.0 0.0M 0) (== 0.0M 0.0 0) (== 0.0M 0 0.0)] [true false false false true false] This is more of a problem with number equality, not the transitivity of ==. (== x1 x2 x3 ... xn) can be rewritten as (and (== x1 x2) (== x2 x3) ... (== xn-1 xn)). So if you compare (== x y z), then if x = y, then the result of (== x z) and (== y z) should be equivalent, considering the numbers are, well, numbers. I believe the issue lies within the bigdec-parsing, which seems to have two zeroes: (== 0M 0.0M) returns false, and their hashcode (0 and 1, respectively) are different. Yea, I think this is the peculiar definition of BigDecimal.equals() biting us here. http://docs.oracle.com/javase/1.4.2/docs/api/java/math/BigDecimal.html # Note: care should be exercised if BigDecimals are to be used as keys in a # SortedMap or elements in a SortedSet, as BigDecimal's natural ordering is # inconsistent with equals. See Comparable, SortedMap or SortedSet for more # information. equals(): # Compares this BigDecimal with the specified Object for equality. Unlike # compareTo, this method considers two BigDecimals equal only if they are # equal in *value* and *scale* (thus 2.0 is not equal to 2.00 when compared by # this method) -- 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
Re: == is not transitive?
I was bitten by this a year ago and posted here: http://groups.google.com/group/clojure/browse_frm/thread/9091ad790fc96b24 My workaround is to call BigDecimal#stripTrailingZeros before passing it to code that might compare it to some other number. user (== 1 (.stripTrailingZeros 1.0M)) true However, there is an edge case: user (== 0 (.stripTrailingZeros 0.0M)) false Which is due to this Java bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6480539 So I use a function like the following instead of bigdec to parse BigDecimals. (defn parse-stripped-bigdec [^String value-str] ;; Note that bigdec uses reflection (at least in Clojure 1.2.1) (let [n (java.math.BigDecimal. value-str)] (if (zero? n) 0M (.stripTrailingZeros n Be aware that stripping the zeros changes how the BigDecimal is formatted by #toString. user (str (parse-stripped-bigdec 10)) 1E+1 So, I have a special case for BigDecimal that calls #toPlainString in the places where I do not want exponential format. user (.toPlainString (parse-stripped-bigdec 10)) 10 I hope that helps. - Pat On Oct 4, 8:39 pm, Ben Wolfson wolf...@gmail.com wrote: user [(== 0 0.0) (== 0.0 0.0M) (== 0.0M 0)] [true true false] user [(== 0 0.0 0.0M) (== 0 0.0M 0.0) (== 0.0 0 0.0M) (== 0.0 0.0M 0) (== 0.0M 0.0 0) (== 0.0M 0 0.0)] [true false false false true false] -- 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
Re: == is not transitive?
On Fri, Oct 5, 2012 at 2:08 AM, Jean Niklas L'orange jeann...@hypirion.com wrote: On Friday, October 5, 2012 2:39:05 AM UTC+2, Ben wrote: user [(== 0 0.0) (== 0.0 0.0M) (== 0.0M 0)] [true true false] When passing two arguments to ==, == will be transitive. I'm not sure what you mean by this. Transitivity means that for all x, y, and z, (Fxy Fyz) = Fxz. But there are values of x, y, and z for which that does not hold. -- 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
== is not transitive?
user [(== 0 0.0) (== 0.0 0.0M) (== 0.0M 0)] [true true false] user [(== 0 0.0 0.0M) (== 0 0.0M 0.0) (== 0.0 0 0.0M) (== 0.0 0.0M 0) (== 0.0M 0.0 0) (== 0.0M 0 0.0)] [true false false false true false] -- 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
Re: == is not transitive?
The only reason for this that I can think of is incomplete rules for casting numbers. On Thursday, 4 October 2012 20:39:05 UTC-4, Ben wrote: user [(== 0 0.0) (== 0.0 0.0M) (== 0.0M 0)] [true true false] user [(== 0 0.0 0.0M) (== 0 0.0M 0.0) (== 0.0 0 0.0M) (== 0.0 0.0M 0) (== 0.0M 0.0 0) (== 0.0M 0 0.0)] [true false false false true false] -- 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
Re: == is not always transitive
I must agree that the behaviour of == is not correct here. The problem is in this method in Numbers.java: public boolean equiv(Number x, Number y){ return toBigDecimal(x).equals(toBigDecimal(y)); } The behaviour we currently have is: user= (let [ones [1 1.0 1N 1M 1.0M 1.00M] ] (doseq [a ones b ones] (println a == b \tab (== a b) ))) 1 == 1 true 1 == 1.0 true 1 == 1N true 1 == 1M true 1 == 1.0M false 1 == 1.00M false 1.0 == 1 true 1.0 == 1.0 true 1.0 == 1N true 1.0 == 1M true 1.0 == 1.0M true 1.0 == 1.00M true 1N == 1 true 1N == 1.0 true 1N == 1N true 1N == 1M true 1N == 1.0M false 1N == 1.00M false 1M == 1 true 1M == 1.0 true 1M == 1N true 1M == 1M true 1M == 1.0M false 1M == 1.00M false 1.0M == 1 false 1.0M == 1.0 true 1.0M == 1N false 1.0M == 1M false 1.0M == 1.0M true 1.0M == 1.00M false 1.00M == 1 false 1.00M == 1.0 true 1.00M == 1N false 1.00M == 1M false 1.00M == 1.0M false 1.00M == 1.00M true I propose we change the method to be: public boolean equiv(Number x, Number y){ return toBigDecimal(x).compareTo(toBigDecimal(y)) == 0; } This makes the previous expression return all true, and == should also be transitive. In particular, (== 1.0M 1.00M) will be true rather than false, which is much more in the spirit of ==. The difference between 1.0M and 1.00M should be checked by calling the scale() method, which makes sense because it is quite an unusual thing to do. I also noticed in test_clojure/numbers.clj the lines: ; TODO: ; == ; and more... So I thought of also adding the test: (deftest equality (are [x y] (== x y) 4242 4242.0 4242N 4242M 4242.0M 4242.00M 42.0 42 42.0 42.0 42.0 42N 42.0 42M 42.0 42.0M 42.0 42.00M 42N 42 42N 42.0 42N 42N 42N 42M 42N 42.0M 42N 42.00M 42M 42 42M 42.0 42M 42N 42M 42M 42M 42.0M 42M 42.00M 42.0M 42 42.0M 42.0 42.0M 42N 42.0M 42M 42.0M 42.0M 42.0M 42.00M 1.23 1.23 1.23 1.23M 1.23M 1.23 1.23M 1.23M ) (are [x y] (not (== x y)) 12 12.1 1.23 123 34 3.4 1.23 1.234 123N 345N 123 345N 123N 345 12.34M 456N 12.34M 4.56 12.34 4.56M 12 4.56M 12M 4.56 12.34M 1.234M )) I think it would be really nice to get this fixed before the 1.4 release. The changes above can be found at https://github.com/andrea-chiavazza/clojure/tree/BigDecimal-equiv-fix Can anybody defend the current behaviour against the one I propose ? -- 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
Re: == is not always transitive
Leif leif.poor...@gmail.com writes: I'd also like to make sure people are aware of this oddity. I discovered this after reading an article about the bad design of PHP. I read that in PHP, == is not transitive. I thought Ha ha ha, that ridiculous PHP! Then I checked c.c/== ; Imagine my reaction when I learned that Clojure had something in common with PHP. o_O, :'[ Other emoticons also washed over me. Clojure's == is numerical equivalence, not equality. - clojure.core/== ([x] [x y] [x y more]) Returns non-nil if nums all have the equivalent value (type-independent), otherwise false The problem with PHP (and JavaScript's) == operator is that the type coercion is not limited to numerical types: PHP 1 == 1= true 1 + 1 = 2 JavaScript 1 == 1= true 1 + 1 = 11 Clojure (== 1 1) = java.lang.ClassCastException (+ 1 1) = java.lang.ClassCastException Clojure's equality function [1], however, does what you expect when comparing floats and integers: (= 1.0 1) = false But it also does what you want when comparing _categories_ of numbers [2] [3]: (let [a (int 1) b (bigint 1)] {:equal_values? (= a b) :equal_types? (= (type a) (type b))}) = {:equal_values? true, :equal_types? false} I think Clojure does a fantastic job of being both convenient and strongly typed. -- guns [1]: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Util.java#L23 [2]: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Numbers.java#L213 [3]: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Numbers.java#L978 If you were really concerned about whether a number is a BigInteger vs Integer, or Float vs Double, you would have to handle that on your own. -- 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
Re: == is not always transitive
Yes, that is one reason why I tend to use BigDecimal instead of float or double. The thing that seems wrong to me is (not (== 1 1.0M)), since these are both exact representations of the value one and the doc for == says that it tests for equivalent value (type- independent). On Apr 11, 10:00 pm, Cedric Greevey cgree...@gmail.com wrote: IME, it's almost never useful to perform equality tests on floating point values. Generally you want to know if they're near enough to one another without necessarily being exactly equal. For that something like (defn f= [f1 f2 threshold] ( (Math/abs (- f1 f2)) threshold)) is probably the sort of thing you want. -- 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
Re: == is not always transitive
I'd also like to make sure people are aware of this oddity. I discovered this after reading an article about the bad design of PHP. I read that in PHP, == is not transitive. I thought Ha ha ha, that ridiculous PHP! Then I checked c.c/== ; Imagine my reaction when I learned that Clojure had something in common with PHP. o_O, :'[ Other emoticons also washed over me. In summary, beware when comparing different numeric types, and don't throw stones even if your house is made of bricks, because the windows are still glass. On Friday, September 2, 2011 12:50:45 PM UTC-7, Patrick Houk wrote: Greetings, I think that I've encountered a bug in ==. user= (and (== 1 1.0) (== 1.0 1.0M) (not (== 1 1.0M))) true This happens with 1.2.1 and 1.3-beta2. I think it has to do with the precision of the BigDecimal. user= (== 1 1.0M) false user= (== 1 1M) true I think a solution would be to use BigDecimal#compareTo (or maybe BigDecimal#stripTrailingZeros) in ==, so that (== 1M 1.0M) becomes true. (I would expect (= 1M 1.0M) to remain false, though.) Thanks, - Pat -- 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
Re: == is not always transitive
IME, it's almost never useful to perform equality tests on floating point values. Generally you want to know if they're near enough to one another without necessarily being exactly equal. For that something like (defn f= [f1 f2 threshold] ( (Math/abs (- f1 f2)) threshold)) is probably the sort of thing you want. -- 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
Re: == is not always transitive
On Wed, Apr 11, 2012 at 5:46 PM, Leif leif.poor...@gmail.com wrote: Then I checked c.c/== ; Imagine my reaction when I learned that Clojure had something in common with PHP. o_O, :'[ It's instructive to look at the result of: (let [ones [1 1.0 1N 1M 1.0M] ] (for [a ones b ones] (== a b))) The first four compare equal in all combinations. 1.0M is equal to 1.0 but unequal to all the others. -- Sean A Corfield -- (904) 302-SEAN An Architect's View -- http://corfield.org/ World Singles, LLC. -- http://worldsingles.com/ 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
== is not always transitive
Greetings, I think that I've encountered a bug in ==. user= (and (== 1 1.0) (== 1.0 1.0M) (not (== 1 1.0M))) true This happens with 1.2.1 and 1.3-beta2. I think it has to do with the precision of the BigDecimal. user= (== 1 1.0M) false user= (== 1 1M) true I think a solution would be to use BigDecimal#compareTo (or maybe BigDecimal#stripTrailingZeros) in ==, so that (== 1M 1.0M) becomes true. (I would expect (= 1M 1.0M) to remain false, though.) Thanks, - Pat -- 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