-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
proposal: Go 2: math/rand: Add Rand.choose(from int, choose int, replace bool) []int #25534
Comments
Could you write a sample doc comment for the new function? Thanks. |
Here's a play with the docs and a first pass at an implementation. I'll inline the doc here for folks who want to make inline comments: // Choose draws choose times from the range [0,from) with(out)
// replacement. For example, r.Choose(10, 3, true) draws 3 times from
// [0,10) with replacement, which is equivalent to []int{r.Intn(10),
// r.Intn(10), r.Intn(10)}. And r.Choose(10, 10, false) draws 10
// times from [0,10) without replacement, which is equivalent to
// r.Perm(10).
//
// Choose will return an error if choose > from and replace is false,
// or if from < 1.
func (r Rand) Choose(from int, choose int, replace bool) ([]int, error) { |
Thanks. That seems possible to write outside the standard library, in a go-gettable package. Is it widely used enough that it ought to be in the standard library? Consider https://golang.org/doc/faq#x_in_std . |
Moving all of math/rand out of the stdlib has been suggested before in #24800, although if you went that route you'd need to vendor it for these: $ git grep math/rand go1.10.2 -- src
go1.10.2:src/archive/zip/writer_test.go
go1.10.2:src/bytes/buffer_test.go
go1.10.2:src/bytes/bytes_test.go
go1.10.2:src/cmd/compile/internal/gc/pgen.go
... But it looks like we already vendor x/crypto, x/net, and x/text, so that's probably not a blocker. But wherever the rand package lives, I think the goal should be to provide flexible primitives for consumers. By adding
where |
Well, yes, I think so. |
I've retitled this issue to use |
So what you're saying is this would be easy to implement on our own? Isn't the whole purpose of the Go stdlib to have minimal tooling?
It would be good to have an alternative to Essentially, using // n: the limit for Intn
// m: the size of the slice
func ChooseWithReplace(n, m int) []int {
slice := make([]int, m)
for i := range slice {
slice[i] = Intn(n)
}
return slice
} You realize that a function like this shouldn't be in the standard library anyway. TL;DR: Remove the boolean flag, don't implement choosing with replacement. Create a function that creates partial permutations, have rand.Perm() either use the new function, or remove rand.Perm() entirely in favor of this one |
I'm having trouble parsing this. Are you saying "why keep
This argument for a public
I agree that it's not hard, but it is inefficient (just like
I think it's a useful optimization. But I'd be fine with caching unused bits instead. Which approach makes more sense in the API can get sorted out if/when we have an internal |
I was saying "why use Choose (with replacement) if it's easily implementable by successive Intn calls"
Then don't use Intn, use |
That's a valid position, but see the token-generation discussion in #25531 for how it's not always trivial. I think getting an efficient implementation into the stdlib, where everyone can share the benefits, is useful. Especially if we deprecate less-general APIs as part of that, since fewer API methods seems like a win for stdlib maintainers. But if the stdlib is not interested in facilitating efficient token generation, that's a maintainer call, and this can all live in an external library. |
Even though we are not moving math/rand outside the standard library, this specific function can easily be implemented outside the standard library and seems too special-purpose to warrant adding to the core math/rand. |
That addresses the API portion of this. Is there interest in improving the over-drawing in |
Not particularly, no. We try not to change the output of these functions from release to release. |
Right, but for Go 2 (as this issue |
This generalizes the current
Perm
, which could be implemented as:(although see here for replacing
Perm
withShuffle
).A
Choose
method could also replaceIntn
:It would also allow for optimizing situations where you would currently use multiple
Intn
calls. For example, ifn
was 256, you could calculate up to eight draws from oneUint64
call. The token-generation use case from here would be:although you'd want something like #25531 to get a crypographically secure source behind those choices. That seems both more efficient and more readable than other approaches I've seen to generating random tokens in bases that are not powers of two.
The text was updated successfully, but these errors were encountered: