SE-0202 Amendment Proposal: Rename Random to DefaultRandomNumberGenerator

SE-0202, as accepted, introduces a type, Random, as the default source of random numbers on each platform.

As @bzamayo outlines here, the name Random for this default source is misleading, and would probably be better named DefaultRandomNumberGenerator.

The core team agrees, so we're opening up a thread to discuss before accepting this amendment.

One open question is the naming of the getter for an instance of the type. Currently it is Random.default. However, renaming Random leads to the rather clunky DefaultRandomNumberGenerator.default. Benjamin suggests .shared. However, in all current implementations, this is not strictly speaking a shared instance – it is instead a getter/setter for a fresh instance each time. This doesn't actually have a cost, since the type has no actual size (the type is just a vehicle for calling an OS function), but needs to be done this way because using: is taken inout.

Any suggestions for better naming gratefully received.

2 Likes

Perhaps .instance ?

Just to provide some slight context, the main reason I had suggested shared is because it is really a 'shared' source of randomness. I realise this is a subtlety that is probably confusing, given how singletons tend to use shared properties to refer to true shared instances, and am certainly open to better ideas.

My main issue was with the name of the Random object itself and still support DefaultRandomNumberGenerator (or DefaultRNG as some complained in the discussion thread that the former was simply too long, even though I believe it will be typed rarely and there are mitigations with autocomplete etc.)

2 Likes

Thanks @bzamayo – that's a good point. My personal opinion is there's no ideal name and any of default, shared or instance is probably fine. The documentation on a given platform should cover the exact nature of the default instance.

Would you consider layering this, retaining Random, and going for Random.DefaultSource.shared? This opens the door for Random.GaussianDistribution, Random.MersenneTwister, Random.ShuffledDistribution, etc, each of which can offer a shared instance?

8 Likes

Probably a silly idea, but if there were a common type named Default, you could define it something like:

extension Default {
  static var randomNumberGenerator: RandomNumberGenerator { return ... whatever you want to call it }
}

And this might be a nice home to all sorts of things that have platform defaults or whatever rather than putting static accessors in the main type itself?

1 Like

I have mixed feelings about this. I do agree that Random as a currency type is probably not the best. However, I do like the idea of a, (pardon the term), namespace that would wrap around various "Random" related items. However given that that is a whole can of worms, I would prefer to just keep it named Random. All the alternatives I've seen are too clunky for my liking.

4 Likes

I like the idea of renaming the Random type to DefaultRandomNumberGenerator. That name seems more descriptive of the actual purpose and behavior of the type.

I think it would be unfortunate, though, for the accessor to be so arduously long (e.g. DefaultRandomNumberGenerator.shared). At the call-site itself, Random.default seems descriptive enough while not being overly verbose.

I think this would be a good time to introduce a Random namespace:

enum Random {
    static var default: DefaultRandomNumberGenerator {
        return DefaultRandomNumberGenerator.shared
    }
}

An approach like this would allow us to keep current (and imo better) call-site semantics while updating the type name itself to be less misleading.

Eventually, other types could have accessors in the Random namespace as well. It would also be a good extension point for users to add their own sources of randomness.

Do we want to do this for all the types that have a default? One occurrence of this naming should not really push the standard library to enforce this naming.

I think we need a more complete approach to default values. I worry that creating a precedence for the name default to be at the beginning is just avoid the problem.

I don't think it's really expected that you would ever see DefaultRandomNumberGenerator.shared at a call site. Given it's the default and all.

The one place users will need it is when defining their own random methods in parallel to the std lib ones, so they can have the same default. The length of the name doesn't seem particularly burdensome for this rare case.

5 Likes

This is an interesting notion – and is immediately interesting for our purposes here because it suggests an alternative possible namespace into which the default source of randomness could go.

Given it's unclear whether the std lib is the right place, long term, for other random-related things (as opposed to such things as distributions belonging in a separate package), it seems inappropriate to use this amendment as a vehicle for creating such a thing. This amendment is about the immediate need to rename this type to something more appropriate as part of the 4.2 release.

Then how about DefaultRandomSource.shared? I don't love it but it's shorter. Or RandomSource, which can be distinct from 3rd parties via Swift.RandomSource?:

We had lengthy discussion in the pitch phase about these kinds of names. These names are not good because the generators themselves are not a source of randomness. For example, calling into /dev/urandom. The file itself sources us randomness while Random takes that and generates a number.

4 Likes

I would like to echo something I said in the previous thread

2 Likes

Why are we over complicating this? 99% of the time you have some novice game develop who wants to roll a die or pick a card. They don't care if it's Mersenne Twister or a radioactive-isotope based RNG.

Progressive disclosure.

1 Like

I like Erica’s idea in particular because it opens the door to a Random.default that points to some standard generator that serves 90% of the need, much in the manner of other languages’ stdlibs, while setting up a sensible naming structure for more specialized RNGs.

If devs have to type DefaultRandomNumberGenerator.shared on a regular basis, Swift will never live it down.

6 Likes

DefaultRandomNumberGenerator.shared sound terrible unwieldy to me - Swift should not hold a competition who designs the ugliest and longest name. Were are the good old times of rnd()? Not every problem have to become rocket science 8(

To reiterate: if anyone has to type DefaultRandomNumberGenerator.shared on a regular basis, something has gone horribly wrong. Users are not expected to use this generator directly. They should use the higher-level APIs. They may use a PRNG of their own as an argument to those functions when paramterizing, but wouldn't ever need to pass in the default value.

If we did find people using it often, this would be a sign we've made it too inviting and that the name Random.default could be a cause of this.

6 Likes

It sounds to me that what you want then is a consensus that DefaultRandomNumberGenerator.default is the right name.

Points in favor:

  • It is highly descriptive and accurate
  • It does not mislead in using default rather than shared as new instances will be created.

Points against:

  • The tooling is overly long and difficult to type.
  • As @Paul_Cantrell notes, it may produce negative feelings about the language if used by third parties. (Reason: "If we did find people using it often, this would be a sign we've made it too inviting and that the name Random.default could be a cause of this.")

Let me ask:

  • Why does there need to be a default member at all rather than using DefaultRandomNumberGenerator()?
  • Why not use a static member that's set on first use, that can be shared?
  • If it is a (to quote from the first post of this thread) "default source", why not name it using those words or a close equivalent? Or is that just a misstatement that should be ignored?
  • Why not create a subtype for the default generator, allowing room for the language to grow or third parties to build on? (Edit: although this might make conformance difficult, and it apparently should not be inviting such customization as this appears to be a type meant to service the rest of the proposal, even though it's visible)

My apparently incorrect impression was that this name would occasionally should up in practical usage. If that's not the case, then I have no objection to a cumbersome name.