[swift-evolution] [Proposal] Random Unification
Xiaodi Wu
xiaodi.wu at gmail.com
Sun Nov 5 21:33:56 CST 2017
That's perfectly fine, I should think. Your 'random' and 'random(using:)'
are distinct too.
On Sun, Nov 5, 2017 at 21:32 Alejandro Alonso <aalonso128 at outlook.com>
wrote:
> An error that came up in development, default arguments cannot use
> internal types, `shuffle(using:)` and `shuffled(using:)`. To remedy this
> issue I would have to add another method requirement with no arguments that
> gives a default implementation of using `_Random`. This would work, but
> would appear in stdlib documentation as two separate functions.
>
> - Alejandro
>
> On Nov 5, 2017, 9:08 PM -0600, Xiaodi Wu <xiaodi.wu at gmail.com>, wrote:
>
> On Sun, Nov 5, 2017 at 8:21 PM, Alejandro Alonso <aalonso128 at outlook.com>
> wrote:
>
>> I can agree with mostly everything in here. I think `.random` on
>> `RandomAccessCollection` should mimic the current design with `.first` and
>> `.last` by returning an optional. In terms of the naming of this, we have
>> to look at how python structures the call site. `random.choice([1, 2, 3,
>> 4])` To me this reads, random choice within this array. This works because
>> of how it’s called. With the proposed solution, we are calling to get a
>> random element directly from the array. So I stick by with naming this
>> random.
>>
>> On the subject of bike shedding the names, I can agree to use
>> `RandomNumberGenerator` whole heartily. As for `Randomizable`, I agree
>> there might be a better name for this, but the question is what?
>>
>
> That is a good question. I don't like `RandomlySamplable`; it might be
> that `Randomizable` could be the least bad option.
>
> One more comment that I neglected to make. You don't need to use an `enum`
> in order to make a type non-initializable. A `struct` can do the same with
> a private init. There are established singleton patterns for Swift and an
> `enum` with a single case is...atypical. I'm also not sure why this should
> be a public type at all. Why expose `Random.default.next()`? Shouldn't the
> user always use `T.random`? Afaict, `Random` can be an internal type
> `_Random` that the user never sees at all.
>
>
> On Nov 5, 2017, 7:56 PM -0600, Xiaodi Wu <xiaodi.wu at gmail.com>, wrote:
>>
>> I like this particular version. In particular, the choice of algorithms
>> is, afaict, correct and that is incredibly important. I had overlooked that
>> `arc4random` is cryptographically secure past a certain version of macOS,
>> but you are absolutely right. I am also on board with the fatal error
>> suggestion if random entropy is unavailable; I think it must be amply
>> documented, though.
>>
>> I do think, however, that you're overloading too many things into the
>> word "random" when they're not the same. Take a look at Python, which is
>> pretty widely used for numerics. There's `rand` and `random` for getting a
>> random integer or floating-point value, and there's `choice` and `sample`
>> for choosing one or more values out of a collection without replacement.
>> These are sufficiently different tasks and don't all need to be called
>> "random" or satisfy the same requirement of the same protocol. Put another
>> way, it's absolutely *not* inconsistent for numeric types to have
>> `random()` while collection types have a differently named method.
>>
>> By contrast, I think the great length of text trying to justify naming
>> all of these facilities `random` in order to parallel `first` and `last`
>> shows how the proposed design is comparatively weaker. You have to argue
>> that (a) `Int.random` shouldn't return an optional value because it'd be
>> unwieldy, and therefore `(0..<5).random` shouldn't either because it would
>> then be inconsistent; but (b) that `(0..<5).random` should be spelled and
>> behave like `(0..<5).first` and `(0..<5).last` even though the user must
>> handle empty collections totally differently because the return types are
>> not the same. Either `(0..<5).random` should behave analogously to `first`
>> and `last` or it should not. If it should, it only makes sense to return a
>> result of type `T?`. After all, if a collection doesn't have a `first`
>> item, then it can't have a `random` item. Put another way, having a `first`
>> item is a prerequisite to having a randomly selectable item. The behavior
>> of the Swift APIs would be very consistent if `first` returns `T?` but
>> `random` returns `T`. However, I agree that unwrapping `Int.random` every
>> time would be burdensome, and it would not make sense to have a type
>> support `random` but not have any instantiable values; therefore, returning
>> an optional value doesn't make sense, and it follows that `Int.random`
>> *shouldn't* behave like `first` or `last`.
>>
>> Once you stop trying to make what Python calls `rand/randint` and
>> `choice/sample` have the same names, then finding a Swifty design for the
>> distinct facilities becomes much easier, and it suggests a pretty elegant
>> result (IMO):
>>
>> ```
>> [1, 2, 3, 4].choice // like `first` or `last`, this gets you a value of
>> type Int?
>> [1, 2, 3, 4].sampling(2) // like `prefix(2)` or `suffix(2)`, this gets
>> you a subsequence with at most two elements
>>
>> Int.random // this gets you a random Int; or it may trap
>> Float.random // this gets you a random Float; or it may trap
>> ```
>>
>> With that, it also becomes clear why--and I agree with you--an
>> independent `Int.random(in: 0..<5)` is not necessary. `(0..<5).choice` is
>> fine, and it can now appropriately return a value of type `T?` because it
>> no longer needs to parallel `Int.random`.
>>
>> * * *
>>
>> More in the bikeshedding arena, I take issue with some of the names:
>>
>> - I reiterate my comment that `Randomizable` is not the best name. There
>> are multiple dictionary definitions of "randomize" and one is "make
>> unpredictable, unsystematic, or random in order or arrangement." Wikipedia
>> gives at least five different contextual meanings for the word. What you're
>> doing here is specifically **random sampling** and we can do better to
>> clarify that, I think.
>>
>> - While I agree that `RNG` can be cryptic, the alternative should be
>> `RandomNumberGenerator` (as it's called in other languages);
>> `RandomGenerator` is not quite accurate. Again, we're _consuming_
>> randomness to _generate_ numbers (or values of other type, based on the
>> result of a generated number). We're not _generating_ randomness.
>>
>>
>> On Sun, Nov 5, 2017 at 6:33 PM, Alejandro Alonso <aalonso128 at outlook.com>
>> wrote:
>>
>>> https://github.com/apple/swift-evolution/pull/760 is the current API
>>> and proposed solution.
>>>
>>> - Alejandro
>>>
>>> On Nov 5, 2017, 6:18 PM -0600, Xiaodi Wu <xiaodi.wu at gmail.com>, wrote:
>>>
>>> My comments are directed to the "more up-to-date" document that you just
>>> linked to in your reply to Jon. Is that one outdated? If so, can you send a
>>> link to the updated proposal and implementation for which you're soliciting
>>> feedback?
>>>
>>>
>>> On Sun, Nov 5, 2017 at 6:12 PM, Alejandro Alonso <aalonso128 at outlook.com
>>> > wrote:
>>>
>>>> The proposal and implementation have the current updated API. The link
>>>> I sent Jon was the one I brought up a few weeks ago which is outdated now.
>>>> The proposal answers all of your questions. As for `.random` being a
>>>> function, some would argue that it behaves in the same way as `.first` and
>>>> `.last` which are properties.
>>>>
>>>> - Alejandro
>>>>
>>>> On Nov 5, 2017, 6:07 PM -0600, Xiaodi Wu <xiaodi.wu at gmail.com>, wrote:
>>>>
>>>> A few quick thoughts:
>>>>
>>>> I know that there's been some discussion that `(1...10).random` is the
>>>> best spelling, but I'd like to push back on that suggestion. When I want a
>>>> random number, I tend to think of the type I want first ("I want a random
>>>> integer") and then a range ("I want a random integer between a and b"), not
>>>> the other way around. My intuition is that `Int.random(in:)` will be more
>>>> discoverable, both on that basis and because it is more similar to other
>>>> languages' syntax (`Math.random` in JavaScript and `randint` in NumPy, for
>>>> example). It also has the advantage that the type is explicit, which I
>>>> think is particularly useful in this case because the value itself is,
>>>> well, random.
>>>>
>>>> I would also argue that, `random` is most appropriately a method and
>>>> not a property; there's no hard and fast rule for this, but the fact that
>>>> the result is stochastic suggests (to me) that it's not a "property" of the
>>>> range (or, for that matter, of the type).
>>>>
>>>> I would reiterate here my qualms about `Source` being the term used for
>>>> a generator. These types are not a _source_ of entropy but rather a
>>>> _consumer_ of entropy.
>>>>
>>>> `UnsafeRandomSource` needs to be renamed; "unsafe" has a specific
>>>> meaning in Swift--that is, memory safety, and this is not it. Moreover,
>>>> it's questionable whether this protocol is useful in any sense. What useful
>>>> generic algorithms can one write with such a protocol?
>>>>
>>>> `XoroshiroRandom` cannot be seeded by any `Numeric` value; depending on
>>>> the specific algorithm it needs a seed of a specific bit width. If you
>>>> default the shared instance to being seeded with an `Int` then you will
>>>> have to have distinct implementations for 32-bit and 64-bit platforms. This
>>>> is unadvisable. On that note, your `UnsafeRandomSource` needs to have an
>>>> associated type and not a generic `<T : Numeric>` for the seed.
>>>>
>>>> The default random number generator should be cryptographically secure;
>>>> however, it's not clear to me that it should be device random.
>>>>
>>>> I agree with others that alternative random number generators other
>>>> than the default RNG (and, if not default, possibly also the device RNG)
>>>> should be accommodated by the protocol hierarchy but not necessarily
>>>> supplied in the stdlib.
>>>>
>>>> The term `Randomizable` means something specific which is not how it's
>>>> used in your proposed protocol.
>>>>
>>>> There's still the open question, not answered, about how requesting an
>>>> instance of the hardware RNG behaves when there's insufficient or no
>>>> entropy. Does it return nil, throw, trap, or wait? The proposed API does
>>>> not clarify this point, although based on the method signature it cannot
>>>> return nil or throw. Trapping might be acceptable but I'd be interested to
>>>> hear your take as to why it is preferable.
>>>>
>>>>
>>>> On Sun, Nov 5, 2017 at 4:43 PM, Alejandro Alonso via swift-evolution <
>>>> swift-evolution at swift.org> wrote:
>>>>
>>>>> For the proof of concept, I had accidentally deleted that one. I have
>>>>> a more up to date one which was discussed a few weeks later.
>>>>> https://gist.github.com/Azoy/15f0518df38df9b722d4cb17bafea4c1
>>>>>
>>>>> - Alejandro
>>>>>
>>>>> On Nov 5, 2017, 4:37 PM -0600, Jonathan Hull <jhull at gbis.com>, wrote:
>>>>>
>>>>> Is there a link to the writeup? The one in the quote 404s.
>>>>>
>>>>> Thanks,
>>>>> Jon
>>>>>
>>>>> On Nov 5, 2017, at 2:10 PM, Alejandro Alonso via swift-evolution <
>>>>> swift-evolution at swift.org> wrote:
>>>>>
>>>>> Hello once again Swift evolution community. I have taken the time to
>>>>> write up the proposal for this thread, and have provided an implementation
>>>>> for it as well. I hope to once again get good feedback on the overall
>>>>> proposal.
>>>>>
>>>>> - Alejandro
>>>>>
>>>>> On Sep 8, 2017, 11:52 AM -0500, Alejandro Alonso via swift-evolution <
>>>>> swift-evolution at swift.org>, wrote:
>>>>>
>>>>> Hello swift evolution, I would like to propose a unified approach to
>>>>> `random()` in Swift. I have a simple implementation here
>>>>> https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This
>>>>> implementation is a simple wrapper over existing random functions so
>>>>> existing code bases will not be affected. Also, this approach introduces a
>>>>> new random feature for Linux users that give them access to upper bounds,
>>>>> as well as a lower bound for both Glibc and Darwin users. This change would
>>>>> be implemented within Foundation.
>>>>>
>>>>> I believe this simple change could have a very positive impact on new
>>>>> developers learning Swift and experienced developers being able to write
>>>>> single random declarations.
>>>>>
>>>>> I’d like to hear about your ideas on this proposal, or any
>>>>> implementation changes if need be.
>>>>>
>>>>> - Alejando
>>>>>
>>>>> _______________________________________________
>>>>> swift-evolution mailing list
>>>>> swift-evolution at swift.org
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> swift-evolution mailing list
>>>>> swift-evolution at swift.org
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>
>>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20171106/e98ca4fc/attachment.html>
More information about the swift-evolution
mailing list