-
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
Undeprecate random #422
Undeprecate random #422
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice! I like it a lot. However, I only read the additions and didn't take a look at what you removed. I also really don't know this library, so take my opinion with a grain of salt :P
src/lib.rs
Outdated
//! - [`gen`] generates a random value that fits the type. | ||
//! For example `let val: u16 = rng.gen()` will just fill an `u16` with 16 | ||
//! random bits. But for floats the value will be generated between 0 and 1; | ||
//! which is more usable than any value between 0 and infinity. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be pedantic: to fill a float with bits does not necessarily result in a number between 0 and infinity. Maybe rather say "is more usable than a completely random float value (including NaN
and infinity)" or something like that...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a random value appropriate for the type.
.. = rng.gen()
produces a random value between 0 and std::u16::MAX
,
I think better to say more useful than usable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generating a value between 0 and infinity is not possible with a uniform distribution, which I think is the bigger issue. Maybe we should also mention that the bits are uniformly sampled.
src/lib.rs
Outdated
//! - [`StdRng`]. In addition to the output being indiscernible from true | ||
//! randomness, this PRNG is unpredictable, even if you know the | ||
//! implementation. This requirement makes it slower and/or use more memory | ||
//! however. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe mention that the property of "unpredictability" is important for cryptography?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could mention that unpredictable PRNGs are usually called called "cryptographically secure PRNGs".
Did you actually define before what the acronym PRGN means?
src/lib.rs
Outdated
//! | ||
//! [`ThreadRng`] abstracts away most of these issues. It uses [`StdRng`], which | ||
//! is always a safe choice. Seeding happens automatically on first use. The | ||
//! PRNG its state is stored in thread local storage, so no need to plumb the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: "The PRNG its state" -> "The PRNG's state"
src/lib.rs
Outdated
//! generate floating point values in the (0, 1) interval. | ||
//! | ||
//! For floating point values you may want to use probability distributions. | ||
//! For example time of decay is often modelled with an exponential |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
,
after "example"... I think?
src/lib.rs
Outdated
//! | ||
//! - [`Rng::shuffle`] can be used to shuffle slices. | ||
//! - [`Rng::choose`] to pick one element at random from a slice, and the | ||
//! functions in the [`seq`] the pick multiple. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: "in the [seq
] module to pick multiple"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, didn't review the entire thing...
... but I have two main issues with this:
- The intro in the API is already long; that's why I moved those examples. Scrolling past the same text every time to get to the API is a nuisance.
- While it makes sense to have some documentation aimed at people less familiar with random number generation, there are also technical users, who may be scared away by highly informal doc like this. So either we need to find a compromise or find a way of moving some of the doc elsewhere.
src/lib.rs
Outdated
//! | ||
//! - a random number generator (RNG); | ||
//! - some function to transform the 'bag of bits' from the RNG to a value you | ||
//! can use. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth mentioning that we call this a distribution here?
src/lib.rs
Outdated
//! | ||
//! There are many kinds of RNGs, with different trade-offs. Rand comes with a | ||
//! default, [`thread_rng`]. The numbers it generates are suitable to use in all | ||
//! situations. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps say:
There are many kinds of RNGs, but we are still able to pick a good all-use default which is fast (amortised performance), has good quality (secure and unbiased), and to automatically make a thread-local instance on first use; we call this
thread_rng
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it! Not sure about "amortised performance", I would probably expand or remove it. (BTW, are we using British or American spelling?) I think "unbiased" could be replaced with "unpredictable".
src/lib.rs
Outdated
//! - [`gen`] generates a random value that fits the type. | ||
//! For example `let val: u16 = rng.gen()` will just fill an `u16` with 16 | ||
//! random bits. But for floats the value will be generated between 0 and 1; | ||
//! which is more usable than any value between 0 and infinity. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a random value appropriate for the type.
.. = rng.gen()
produces a random value between 0 and std::u16::MAX
,
I think better to say more useful than usable
src/lib.rs
Outdated
//! which is more usable than any value between 0 and infinity. | ||
//! - [`gen_range`] samples from a specific range of values; | ||
//! - [`sample`], for all situations where you need something slightly more | ||
//! complex. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add fill
to this list?
src/lib.rs
Outdated
//! of them, by measuring different kinds of noice/jitter in the hardware. | ||
//! | ||
//! What is always used instead is a psuedo-random number generator. This is a | ||
//! clever algorithm that can produce an infinite stream of random numbers from |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
psuedo-random or apparently random; the values are not actually random (by the usual definitions)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: psuedo -> pseudo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll change it here. But I don't think we should get too pedantic and call it pseudo-random
everywhere. It is theoretically right, but not an all that interesting distinction.
src/lib.rs
Outdated
//! What is always used instead is a psuedo-random number generator. This is a | ||
//! clever algorithm that can produce an infinite stream of random numbers from | ||
//! a small seed. There exist algorithms that produce random numbers that are in | ||
//! no measurable way any less random than pulling values 'out of thin air'. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Untrue: if you know the seed, you can reproduce
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pedantically speaking, even cryptographic RNGs may be distinguished from true randomness. The definition says it cannot be done in polynomial time. So I would suggest to say "in no practical way" and add the caveat "without knowing the seed".
src/lib.rs
Outdated
//! | ||
//! - [`thread_rng`] is what you often want to use. | ||
//! - If you want more control or better performance, use [`StdRng`] or | ||
//! [`SmallRng`]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SmallRng
is not always faster — maybe emphasise benchmarking? Also for more control one should specify the algorithm. I think the main use-case for specifying StdRng
is going to be in generic code.
Yes. I am not sure what would be a better place. Maybe we can hope this is temporary, and doxidize gets available soon? |
src/lib.rs
Outdated
//! # Getting random values | ||
//! | ||
//! To quickly get you started, the easiest and most high-level way to just get | ||
//! some random value is to use [`random()`]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think "some random value" is too vague. Please mention that it is from a uniform distribution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hoped to avoid terminology until we get below
As soon as you need something slightly more specific, like a random value in some range, you have to know a bit more about how things work, which are discussed below.
src/lib.rs
Outdated
//! ``` | ||
//! | ||
//! This functionality is however very basic. As soon as you need something | ||
//! slightly more specific, like a random value in some range, you have to know |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer "a random value sampled from a specific distribution". It's more precise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The point of this documentation seems to be that it is not very precise. Which doesn't suit all of us...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hope that is not the case... I thought the goal was to be beginner-friendly, maybe that is possible while being precise?
For now we could simply link to Markdown files on GitHub — slightly ugly, but works. Or we could do something like add empty submodules just for extra documentation pages (very ugly in a different way). |
src/lib.rs
Outdated
//! - [`SmallRng`]. Uses little memory, and is very fast. | ||
//! Note: The currently picked algorithm is not ideal, but in a future version | ||
//! the values will for all practical purposes be statistically indiscernible | ||
//! from true randomness. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this will ever be true for SmallRng
. Either it is unpredictable and thus cryptographically secure, or we should not claim so. I suggest to not talk about predictability or to say that it is not guaranteed to be unpredictable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"for all practical purposes be statistically indiscernible from true randomness" means something very different than "unpredictable and thus cryptographically secure".
Because the next lines says "In addition to the output being indiscernible from true randomness, this PRNG is unpredictable", I hope readers will understand that CSPRNGs set a higher standard and offer additional guarantees.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A "random" source is discernible from true randomness if it is predictable. There's scope for confusion here.
@@ -146,7 +143,7 @@ impl CryptoRng for ThreadRng {} | |||
/// If you're calling `random()` in a loop, caching the generator as in the | |||
/// following example can increase performance. | |||
/// | |||
/// ``` | |||
/// ```rust |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the rust
is redundant. (However, I guess it does not hurt to be explicit.)
@@ -166,8 +163,7 @@ impl CryptoRng for ThreadRng {} | |||
/// ``` | |||
/// | |||
/// [`thread_rng`]: fn.thread_rng.html | |||
/// [`Rand`]: trait.Rand.html | |||
#[deprecated(since="0.5.0", note="removed in favor of thread_rng().gen()")] | |||
/// [`Standard`]: distributions/struct.Standard.html |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should mention the disadvantages over using thread_rng().gen()
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is needed — there's already a note about caching the thread_rng
handle above
I tried to make some of the documentation collapsible with some extra css, but the html Rustdoc outputs doesn't make that easy. Not ready to pull out js, I never serriously used that. Maybe interesting for comparison, regex and log also have a pretty long introduction. And there now also is a |
Added |
The documentation is already collapsible (click the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pitdicker could you please separate out the first commit (un-deprecation) and move the other commits (about top-level doc) to a new PR?
@@ -166,8 +163,7 @@ impl CryptoRng for ThreadRng {} | |||
/// ``` | |||
/// | |||
/// [`thread_rng`]: fn.thread_rng.html | |||
/// [`Rand`]: trait.Rand.html | |||
#[deprecated(since="0.5.0", note="removed in favor of thread_rng().gen()")] | |||
/// [`Standard`]: distributions/struct.Standard.html |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is needed — there's already a note about caching the thread_rng
handle above
/// Generates a random value using the thread-local random number generator. | ||
/// | ||
/// This is simply a shortcut for `thread_rng().gen()`. See [`thread_rng`] for | ||
/// documentation of the entropy source and [`Rand`] for documentation of | ||
/// documentation of the entropy source and [`Standard`] for documentation of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a quick mention of using thread_rng().gen_range(a, b)
here? That (and maybe a link to Rng
) is enough though; we don't need to go over everything here.
189b4f6
to
a2a903c
Compare
Ok, done. I am trying something slightly crazy in this branch: moving all |
Now that this PR is tiny, is it ok to merge? (and tackle the documentation in the other PR?) |
It's good enough I guess though there are still outstanding comments. |
I won't forget them, but would like to make the documentation changes part of #423. |
Undeprecate
random()
as discussed in #289.Mostly with this PR I took a stab at making the documentation a bit more friendly for people who don't yet know much about generating random numbers. The documentation did become a bit much I am afraid...