-
Notifications
You must be signed in to change notification settings - Fork 432
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Distribution sample prototype and sized-ness of Rng
#287
Comments
|
I think 4 sounds like a rustc bug for which we should minimize and raise an issue. It's clear |
Thanks. But do you recommend |
I donno.. At this point, you've written more distributions than anyone, so did you prefer writing them with the higher or lower level method? :) It might not matter much actually if distributions will mostly build directly on other distributions. I've no idea why It's possible the It's also likely almost all |
Suggested in rust-random#287 and appears to work
It works, but using |
True; conceptually |
Suggested in rust-random#287 and appears to work
Contrast (trait from my branch but similar to pub trait Choose<T> {
fn choose<R: RngCore>(self, rng: R) -> Option<T>;
}
#[test]
fn dyn_dispatch() {
let mut r: &mut RngCore = &mut ::test::rng(813);
// here we take a second reference to r only so that we don't consume:
assert_eq!([7, 7][..].choose(&mut r), Some(&7));
// ... (including more uses of r)
} with: pub trait Choose<T> {
fn choose<R: RngCore + ?Sized>(self, rng: &mut R) -> Option<T>;
}
#[test]
fn dyn_dispatch() {
let r: &mut RngCore = &mut ::test::rng(813);
assert_eq!([7, 7][..].choose(r), Some(&7));
// the above does not consume r ...
} Both support usage of type-erased I guess the conclusion is that the first version is nicer to write the impls for, but the second is nicer to use, and avoids the |
I'm hoping to get the reborrow thing resolved in which case we can use the more concise syntax, but realistically this will take months to get into stable Rust, even if implemented and merged soon. However, we could still use the As for |
Distributions can be used outside of Rand also, and we want them to depend on the 'front-end' |
I don't think it makes any difference at all. The way I see it you build distributions on top of other distributions as much as possible, thus for many of them there's no need to use the back-end directly at all. I suppose we could use |
Something else occurs to me: Annoying though this is, I think it means we cannot use |
Is there a problem with doing |
But why do that? I think now the best option is Given appropriate language support I might advocate |
I suppose an argument for pursuing the latter is that Adapting the method signature to that later should have no effect at call sites, but would require all impls of |
We need |
It looks like the sole remaining question here is What I still don't understand is why |
|
If we make the distributions take an unsized |
Maybe ask around somewhere else, like the rust repro or irc? |
I'm thinking actually maybe the compiler simply proves that The impl rules in The weird bit is when using The bit I still don't get is whether this equivalence is by language design or just happens to be so, and might not easily be reproduced in another hypothetical Rust compiler (I've seen people complaining about the lack of a proper standard for how the typing system works). |
@nikomatsakis could I ask for your thoughts on this? (Basically first post, plus the reborrow version we both decided to leave for now.) See:
|
What do you think of this test? #[test]
fn test_rng_trait_object_2() {
use distributions::Normal;
fn get_normal<R: Rng + ?Sized>(rng: &mut R) -> f64 {
let normal = Normal::new(2.0, 3.0);
rng.sample(normal)
}
let rng = rng(110);
let mut r = Box::new(rng) as Box<RngCore>;
println!("{}", get_normal(&mut r));
} Edit: updated We make the rng into a trait object with |
|
Updated the comment above... |
I think you are mostly right, but nothing magical is happening. By using |
Right now If you wanted a method to take I've do not quite understand trait objects with methods having polymorphic arguments, like
or
At first blush, I suppose a I doubt these hypothetical type erasures would improve execution speed here, or ever, because the vtable gets built at compile time, but they should reduce code size dramatically because the vtable for I do not know if trait object methods can improve code size here, or maybe they make code size worse, and they only function to replace non-existent
We could maybe avoid expanding the
|
I don't think the vtable will contain monomorphized functions; I'm pretty sure generic functions are simply not available when |
I'm way outside my knowledge here but actually all existing In general, I'd expect vtables necessarily contain monomorphized functions. In particular,
In out case, I wonder if a type cannot be promoted to a trait object, so maybe the trait object method suffices to keep the vtable for
Anyways I think rustc cannot optimize |
Suggested in #287 and appears to work
Going to close since I'm reasonably happy with the way this works now. |
Currently we have:
In my
masterexperimental branch theDistribution
trait is slightly different:Are they equivalent? Almost, but:
What doesThe constraint is relaxed.R: Rng + ?Sized
mean whenRng: Sized
and why does this work?Why doesUniform.sample(&mut r)
wherer: &mut RngCore
work in the latter case? This does work in both cases which is the main thing.Rng
is implemented for everyRngCore
so effectivelyr: &mut Rng
.Rng
andRngCore
to implementDistribution
in the latterIt is often necessary to writemut rng
when implementingDistribution
in the latterAre there any subtleties I'm missing? The former is slightly more convenient, but I don't understand it as well as the latter. @burdges do you understand this better?
The text was updated successfully, but these errors were encountered: