`Base.rand` but `Random.rand!`?

It doesn’t make sense to me that rand is in Base but rand! is in in the stdlib Random. I get that all the other random number related stuff got moved but this seems inconsistent to me.

What was the reasoning here? I’d open an issue/PR if other people find this inconsistent as well.

Both are in Random. You can check it with @which rand() and @which rand!([1.0]). But rand is apparently loaded into Base. I presume it’s because rand so widely used and useful. It’s a balancing act between consistency and convenience.

Thanks. Still I think it’s inconsistent to only load rand into base and not rand!.

See the discussion at https://github.com/JuliaLang/julia/pull/24874

But is it a useful inconsistency or just an annoying inconsistency (or even a foolish inconsistency)?

@cormullion, I’d say it’s an annoying inconsistency.

BTW, randn is also in Base.

Personally I think it’s a useful inconsistency! Mac users probably know that weird “drag a disk to the trash to eject it” inconsistency…

It is strange that what annoys you is actually the thing that’s done right! Would you like to kill two birds with one stone instead? Ask for the reverse, Random returns back to Base. Now you get your “consistency” and all folks get back their convenience as a plus. Random numbers are crucial for scientific computing languages especially dynamic ones like Julia. Despite all the magnificent decisions Julia has made recently, moving Random out of Base wasn’t one of them.

This has been discussed a lot, but moving things out of Base into the standard libraries does not in any way signal that they are unimportant. Also, while there is a minor inconvenience, there are also benefits: eg independent updates of the standard libraries, or conversely, using a particular version even if Julia is updated.

1 Like

No, I’m not saying that Random module should return back to Base, it originally was out of Base. I mean at least rand(), randn(), srand() (I mean the “new” ehm ehm … Random.Seed!()) should remain in Base. For interactive/exploratory/dynamic work, which Julia excels at, these are too essential. Many scientific languages and non-scientific ones do the same thing. Look at MATLAB, R, Mathematica, Crystal, GO, C (stdlib), Fortran, etc., they all make some form of rand available by default. Other advanced/special purpose generators like xoroshiro128 and others remain in the Random module as was the situation before Julia 1.0.

  • Go: random number generation requires importing "math/rand", just like Julia
  • C: random numbers require you to #include <stdlib.h> and seeding the RNG (using the current time) also requires you to #include <time.h>
  • Crystal: random numbers live within the Random module, just like Julia
  • R: rng seed lives in Random.seed, much like Julia
5 Likes

First three are non-interactive and not in the same boat with Julia, Crystal has rand and R has runif() and rnorm() by default plus a plethora of statistical distributions:

  1. Beta
  2. Binomial
  3. Cauchy
  4. Chi-Squared
  5. Exponential
  6. F
  7. Gamma
  8. Geometric
  9. Hypergeometric
  10. Logistic
  11. Log Normal
  12. Multinomial
  13. Negative Binomial
  14. Normal
  15. Poisson
  16. Student t
  17. Uniform
  18. Weibull

Julia is supposedly one step forward over all predecessors.

Summary: Please leave rand and randn as they are and hopefully srand() joines them back as it complements their use if some one wants a repeatable measurement.

Julia 1.0 is a stable release. There is no danger of anything being removed from Base in the entire 1.x timeline.

4 Likes

What’s wrong with seed! (small s)? It’s clearly a better name than srand, which was weird. Also, most people don’t use it anyway (I’ve used the Matlab version of it maybe 5 times over 20 years.)

rand and randn are already where you want them, and seed! is so obscure that hardly anyone needs it.

I don’t agree that progress means putting more stuff into the global workspace…

2 Likes

I see I wasn’t clear in my initial post. I would like to see rand and rand! available per default, everything else per using Random.

I have to say that I was really dismayed that LinearAlgebra, Statistics and Random were moved out of Base but as time goes on I increasingly see the wisdom in this.

As much as I agree that the functionality in these packages are absolutely crucial and having to do using LinearAlgebra makes me feel dirty, the development of stdlib really, really needs to be decoupled from core julia to whatever extent possible.

Let me give an example. Just today, I found a really scary performance regression in sparse(transpose(A)) where A is sparse. Fortunately, I discovered that this is just a bug in sparse, you can fix this easily by doing SparseMatrixCSC(transpose(A)) instead. So now we’re in a place where we have to wait until Julia 1.0.1 for that bug to be fixed. Suppose the regression were real and there were no easy fix. Then we’d be in a pickle, the hacked solution would not be pretty. Once stdlib is separate from Julia itself, fixes to packages like SparseArrays will happne much more rapidly.

So yeah, using LinearAlgebra, Statistics, Random sucks, but it’s more important that we can upgrade and fix those packages at a faster rate than Julia itself is upgraded.

5 Likes

Sure, seed!() is a very nice name. The problem is you must do using Random everywhere you need this.

julia> Random.seed!()
ERROR: UndefVarError: Random not defined
Stacktrace:
 [1] top-level scope at none:0

julia> using Random

julia> Random.seed!()
MersenneTwister(UInt32[0xcaa86f85, 0xeac61058, 0x93421853, 0xd4df5941], Random.DSFMT.DSFMT_state(Int32[1269422445, 1073532173, 1732890801, 1072777308, -2140488122, 1072829781, 1035566119, 1073555375, -2061168306, 1073494504  …  -770156497, 1073546319, 1999375680, 1073621645, 860750873, 614789294, -1729250630, 864726483, 382, 0]), [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], UInt128[0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000  …  0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000], 1002, 0)

You can write:

using Random: seed!

or

import Random.seed!