Skip to content

Deprecate random and weak_rng, add SmallRng#296

Merged
pitdicker merged 5 commits into
rust-random:masterfrom
vks:remove-random
Mar 13, 2018
Merged

Deprecate random and weak_rng, add SmallRng#296
pitdicker merged 5 commits into
rust-random:masterfrom
vks:remove-random

Conversation

@vks

@vks vks commented Mar 12, 2018

Copy link
Copy Markdown
Contributor

See #289.

@dhardy dhardy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good other than the replacement for weak_rng which I'm not sure about — we could just make users copy that snippet (at least it explains how it works), but I don't want to make common tasks hard (to remember how to do).

Comment thread src/lib.rs
//! means that often a simple call to `rand::random()` or `rng.gen()` will
//! suffice, but sometimes an annotation is required, e.g.
//! `rand::random::<f64>()`.
//! The key function is `Rng::gen()`. It is polymorphic and so can be used to

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably wants a bit more re-writing, but this doesn't have to be done now.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we should advertise Rng::sample or Distribution::sample instead and possibly get rid of Rng::gen. But this is still under discussion in #293.

Comment thread benches/misc.rs
#[bench]
fn misc_shuffle_100(b: &mut Bencher) {
let mut rng = weak_rng();
let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really not very ergonomic; we've gone from 1 identifier to 4 with lots of extra syntax too. Any better ideas?

Error handling is pedantic because thread_rng will almost never fail, but we can't really be removed from from_rng.

We could allow something like thread_rng().new_rng::<SmallRng>() but it's not a lot better and adds a function to Rng which doesn't have many other uses.

We could just rename weak_rng to small_rng. Not sure.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure it's an issue outside of small examples. Usually you want to reuse thread_rng(). Maybe something like the following makes it more clear in the examples:

// Create a big, expensive to initialize and slower, but unpredictable RNG.
// This automatically done only once per thread.
let mut thread_rng = thread_rng();
// Create small, cheap to initialize and fast RNG with a random seed.
// This is very unlikely to fail.
let mut small_rng = SmallRng::from_rng(&mut thread_rng).unwrap();

This is even more verbose, but it teaches the correct pattern.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also wrong: thread_rng() is only slow on the first call per thread. SmallRng::new() would be faster if thread_rng was never otherwise used — but chances are good that it would be used somewhere, I guess (at least once std's hash function randomisation uses this, not its own version).

Yes, copy-pasting this is fine, but often people don't look up the doc, they just vaguely remember how to do something and think, ah, SmallRng::new() should work.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also wrong: thread_rng() is only slow on the first call per thread.

That's what I was trying to say with "This automatically done only once per thread.", but I guess it could be said more clearly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any better ideas?

We could implement NewRng for SmallRng such that it uses thread_rng(). However, this requires getting rid of the impl for SeedableRng or specialization, which is not stable yet.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using NewSeeded everywhere is fine. It is also how things used to be until a few months ago. But it would be nice to mention the thread_rng() method in the documentation just to point out a potential (small) performance advantage. How often will initializing the RNG be a bottleneck?

And I am still not sure thread_rng() is used all that much always. There is std::collections::HashMap that may also use it in the future, and maybe a crates dependency. If it is otherwise not used, spinning up thread_rng for one initialization of SmallRng is wasteful.

@dhardy

dhardy commented Mar 12, 2018

Copy link
Copy Markdown
Member

Oh, and I was less sure about removing random(), but searching GitHub mostly shows boring test code and some examples of how not to use random.

@pitdicker

Copy link
Copy Markdown
Contributor

Looks good to me!

Now initializing using `NewRng` is used to simplify the examples. The
documentation for `SmallRng` recommends using `thread_rng` when
initializing a lot of generators.
@vks

vks commented Mar 13, 2018

Copy link
Copy Markdown
Contributor Author

But it would be nice to mention the thread_rng() method in the documentation just to point out a potential (small) performance advantage.

I changed the examples to use NewRng and suggested the thread_rng variant in the documentation of SmallRng.

@dhardy

dhardy commented Mar 13, 2018

Copy link
Copy Markdown
Member

Looks good to me! @pitdicker feel free to merge.

One small thing stands out, but it's definitely beyond the scope of this PR: thread_rng() either succeeds or panics, while new() and from_rng(rng) return a Result. Since errors are rare and new is supposed to be a convenience function (also easy to avoid if required), perhaps new should not return a Result and simply panic on failure?

@pitdicker pitdicker merged commit 2a8cb17 into rust-random:master Mar 13, 2018
@pitdicker

Copy link
Copy Markdown
Contributor

Since errors are rare and new is supposed to be a convenience function (also easy to avoid if required), perhaps new should not return a Result and simply panic on failure?

Seems like a good idea to me (after getting used to it...)!

@vks vks deleted the remove-random branch March 13, 2018 15:46
@dhardy dhardy mentioned this pull request Mar 14, 2018
3 tasks
pitdicker added a commit that referenced this pull request Apr 4, 2018
Deprecate `random` and `weak_rng`, add `SmallRng`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants