> On Nov 30, 2017, at 2:30 PM, Xiaodi Wu <xiaodi...@gmail.com> wrote: > > On Thu, Nov 30, 2017 at 3:58 PM, Dave DeLong via swift-evolution > <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: > > >> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >> >> I would personally go with: >> >> Int.random //Returns a random Int > > “Type.random” is so rarely used as to not be worth the addition, IMO. If you > really need a random element from the *entire* domain, then I think you > should have to manually create the ClosedRange<T> yourself. > >> Int.random(in: ClosedRange<Int>) //Works for Comparable types. Gives a >> result from the closed range. Closed Range is never empty. > > This is redundant. In order to pick a random element, you’re saying I should > have to do “Int.random(0 ..< 10)”? The redundancy here is that I have to > specify Int twice: once for the “.random” call, and again for the type of the > range. We can do better than that. > >> [0,2,3].randomElement //Returns a random element from the collection > > I strongly believe this should be a method, not a property. Properties, like > .first and .last, are expected to return the same value each time you access > them. “.random” inherently breaks that. > > FWIW--and this isn't a vote, I know--I largely agree with Dave DeLong's > conclusions above, and for substantially the same reasons. >> >> Then a version of each with a ‘using:’ parameter which takes a >> generator/source: >> >> Int.random(using: RandomSource) //Returns a random Int using the given >> source of randomness >> Int.random(in: ClosedRange<Int>, using: RandomSource) >> [0,2,3].randomElement(using: RandomSource) >> >> In my own RandomSource & RandomSourceCreatable protocols, I frequently use >> random colors and sizes as well. The issue there is that you really want a >> closed range for each dimension. I wish Swift had a better notion of >> dimensionality baked into the language. >> >> What I ended up doing was having a “constraints” parameter which took an >> array of constraints which corresponded to various dimensions. It works for >> me, but it might be a bit complex for something in the standard library. >> >> Honestly, given the current capabilities of Swift what this really calls for >> is custom initializers/functions for dimensional types: >> >> UIColor.random //This comes from the protocol >> UIColor.random(hue: ClosedRange<CGFloat> = 0…1, saturation: >> ClosedRange<CGFloat> = 0…1, brightness: ClosedRange<CGFloat> = 0…1, alpha: >> ClosedRange<CGFloat> = 1…1) >> //…and of course the same as above, but with ‘using:' >> >> Then you can easily get random colors which look like they belong together: >> >> let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6) >> >> There would probably also be a convenience version taking CGFloats and >> passing them to the real function as ranges: >> >> let myColor = UIColor.random(saturation: 0.2, brightness: 0.6) >> >> >> This means that our default RandomSource needs to be publicly available, so >> that the custom functions can use it as the default… > > > It does not. Having actually implemented some version of these APIs, it's > readily apparent now to me that all custom types can simply call > Int.random(in:) (or UnsafeRawBufferPointer<T>.random(byteCount:), or whatever > else we want to have in the standard library) to get random values from the > default RNG for any built-in type and size. The actual default random need > never be exposed publicly, and since its functions are strictly redundant to > these other APIs (which, of course, are the "currency" APIs that our purpose > here is to design and make public), the default random is required only for > internal implementation of the "currency" APIs and (a) is better off *not* > exposed; (b) doesn't need to be of the same type as other RNGs, conform to > the same protocols, or for that matter, does not even need to be a type or be > written in Swift.
I have also implemented some version of these APIs, both for Random and RepeatablyRandom sources. I get what you are saying about just being able to use the constructs from Int, etc…, but we still need a public default. Let me give a concrete example of CGSize. Yes, we want to just use CGFloat’s random, but if we don’t have a publicly available way to call the default then we have to implement the same algorithm twice, which is problematic. (Code written in Mail) static func random(width widthRange: ClosedRange<CGFloat>, height heightRange: ClosedRange<CGFloat>, using source: RandomSource = .default) -> CGSize { let w = CGFloat.random(in: widthRange, using: source) let h = CGFloat.random(in: heightRange, using: source) return CGSize(width: w, height: h) } Without the default I would have to have a second version which used CGFloat(in:) in order to use the default source/generator, which means I would have to update both places when I make changes. Much better to just allow a default value for ‘using:'. Thanks, Jon > > > 👍 > >> >> Thanks, >> Jon >> >> >>> On Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>> >>> You say that all the `.random`s have different semantics, but to me (at >>> least), they are all very similar. All the methods can be summarized as >>> selecting a single random element from a collection >>> `[0, 2, 3].random` selects a single element from the given collection >>> `Int.random(in: 0…8)` selects a single element from the given range >>> `Int.random` has no range, but selects a single element from the collection >>> of all ints (equivalent to if the above method had a default value for its >>> range) >>> So to me these are all doing the same operation, just with different types >>> of inputs >>> >>>> 2017/11/24 20:07、Alejandro Alonso <aalonso...@outlook.com >>>> <mailto:aalonso...@outlook.com>>のメール: >>>> >>>> >>>> - Alejandro >>>> >>>> ---------- Forwarded message ---------- >>>> From: Xiaodi Wu <xiaodi...@gmail.com <mailto:xiaodi...@gmail.com>> >>>> Date: Nov 24, 2017, 3:05 PM -0600 >>>> To: Alejandro Alonso <aalonso...@outlook.com >>>> <mailto:aalonso...@outlook.com>> >>>> Cc: Brent Royal-Gordon <br...@architechies.com >>>> <mailto:br...@architechies.com>>, Steve Canon via swift-evolution >>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> >>>> Subject: Re: [swift-evolution] [Proposal] Random Unification >>>> >>>>> On Fri, Nov 24, 2017 at 2:55 PM, Alejandro Alonso <aalonso...@outlook.com >>>>> <mailto:aalonso...@outlook.com>> wrote: >>>>> Regarding naming too many things “random”, I’ve talked to many developers >>>>> on my end and they all don’t find it confusing. This proposal is aimed to >>>>> make it obvious what the operation is doing when regarding random. I >>>>> still agree that the proposed solution does just that and in practice >>>>> feels good to write. >>>>> >>>>> I must disagree quite strongly here. The various facilities you name >>>>> "random" have different semantics, and differences in semantics should be >>>>> reflected in differences in names. It doesn't matter that some people >>>>> don't find it confusing; it is objectively the case that you have named >>>>> multiple distinct facilities with the same name, which leads to >>>>> confusion. I, for one, get confused, and you can see on this list that >>>>> people are using arguments about one property named "random" to discuss >>>>> another property named "random". This is quite an intolerable situation. >>>>> >>>>> I disagree that sample is the correct naming to use here. Getting a >>>>> sample is a verb in this context which would make it break API guidelines >>>>> just as well as `pick()`. To sample is to “take a sample or samples of >>>>> (something) for analysis.” I can agree to use `sampling()` which follows >>>>> API guidelines. This would result in the following grammar for `[“hi”, >>>>> “hello”, “hey”].sampling(2)`, “From array, get a sampling of 2" >>>>> >>>>> "Sampling" is fine. >>>>> >>>>> >>>>> On Nov 23, 2017, 12:54 AM -0600, Xiaodi Wu , wrote: >>>>>> On Wed, Nov 22, 2017 at 23:01 Alejandro Alonso <aalonso...@outlook.com >>>>>> <mailto:aalonso...@outlook.com>> wrote: >>>>>> Like I’ve said, python has different syntax grammar. We have to read >>>>>> each call site and form a sentence from it. `random.choice([1, 2, 3])` >>>>>> to me this reads, “Get a random choice from array”. This makes sense. >>>>>> Slapping the word choice as an instance property like `[1, 2, 3].choice` >>>>>> reads, “From array, get choice”. What is choice? This doesn’t make sense >>>>>> at all to me. To me, the only good solution is `[1, 2, 3].random` which >>>>>> reads, “From array, get random”. I actually think most users will be >>>>>> able to understand this at first glance rather than choice (or any or >>>>>> some). >>>>>> >>>>>> Again, my concern here is that you are proposing to name multiple things >>>>>> "random". If this property should be called "random"--which I'm fine >>>>>> with--then the static method "random(in:)" should be named something >>>>>> else, and the static property "random" should be dropped altogether (as >>>>>> I advocate for reasons we just discussed) or renamed as well. It is >>>>>> simply too confusing that there are so many different "random" methods >>>>>> or properties. Meanwhile, isn't your default RNG also going to be called >>>>>> something like "DefaultRandom"? >>>>>> >>>>>> In regards to the sample() function on collections, I have added this as >>>>>> I do believe this is something users need. The name I gave it was pick() >>>>>> as this reads, “From array, pick 2”. >>>>>> >>>>>> The name "sample" has been used to good effect in other languages, has a >>>>>> well understood meaning in statistics, and is consistent with Swift >>>>>> language guidelines. The operation here is a sampling, and per Swift >>>>>> guidelines the name must be a noun: therefore, 'sample' is fitting. >>>>>> "Pick" does not intrinsically suggest randomness, whereas sample does, >>>>>> and your proposed reading uses it as a verb, whereas Swift guidelines >>>>>> tell us it must be a noun. I would advocate strongly for using >>>>>> well-established terminology and sticking with "sample." >>>>>> >>>>>> >>>>>> On Nov 17, 2017, 8:32 PM -0600, Xiaodi Wu via swift-evolution >>>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>, wrote: >>>>>>> On Fri, Nov 17, 2017 at 7:11 PM, Brent Royal-Gordon >>>>>>> <br...@architechies.com <mailto:br...@architechies.com>> wrote: >>>>>>>> On Nov 17, 2017, at 3:09 PM, Xiaodi Wu via swift-evolution >>>>>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>>>>>>> >>>>>>>> But actually, Int.random followed by % is the much bigger issue and a >>>>>>>> very good cautionary tale for why T.random is not a good idea. Swift >>>>>>>> should help users do the correct thing, and getting a random value >>>>>>>> across the full domain and computing an integer modulus is never the >>>>>>>> correct thing to do because of modulo bias, yet it's a very common >>>>>>>> error to make. We are much better off eliminating this API and >>>>>>>> encouraging use of the correct API, thereby reducing the likelihood of >>>>>>>> users making this category of error. >>>>>>> >>>>>>> Amen. >>>>>>> >>>>>>>> If (and I agree with this) the range-based notation is less intuitive >>>>>>>> (0..<10.random is certainly less discoverable than Int.random), then >>>>>>>> we ought to offer an API in the form of `Int.random(in:)` but not >>>>>>>> `Int.random`. This does not preclude a `Collection.random` API as >>>>>>>> Alejandro proposes, of course, and that has independent value as >>>>>>>> Gwendal says. >>>>>>> >>>>>>> >>>>>>> If we're not happy with the range syntax, maybe we should put >>>>>>> `random(in:)`-style methods on the RNG protocol as extension methods >>>>>>> instead. Then there's a nice, uniform style: >>>>>>> >>>>>>> let diceRoll = rng.random(in: 1...6) >>>>>>> let card = rng.random(in: deck) >>>>>>> let isHeads = rng.random(in: [true, false]) >>>>>>> let probability = rng.random(in: 0.0...1.0) >>>>>>> >>>>>>> // Special FloatingPoint overload >>>>>>> >>>>>>> The only issue is that this makes the default RNG's name really >>>>>>> important. Something like: >>>>>>> >>>>>>> DefaultRandom.shared.random(in: 1...6) >>>>>>> >>>>>>> Will be a bit of a pain for users. >>>>>>> >>>>>>> I did in fact implement this style of RNG in NumericAnnex, but I'm not >>>>>>> satisfied with the design myself. Not only is it a bit of an ergonomic >>>>>>> thorn, there's also another drawback that actually has weighty >>>>>>> implications: >>>>>>> >>>>>>> Users aren't conditioned to reuse RNG instances. Perhaps, it is because >>>>>>> it can "feel" wrong that multiple random instances should come from the >>>>>>> *same* RNG. Instead, it "feels" more right to initialize a new RNG for >>>>>>> every random number. After all, if one RNG is random, two must be >>>>>>> randomer! This error is seen with some frequency in other languages >>>>>>> that adopt this design, and they sometimes resort to educating users >>>>>>> through documentation that isn't consistently heeded. >>>>>>> >>>>>>> Of course, you and I both know that this is not ideal for performance. >>>>>>> Moreover, for a number of PRNG algorithms, the first few hundred or >>>>>>> thousand iterations can be more predictable than later iterations. >>>>>>> (Some algorithms discard the first n iterations, but whether that's >>>>>>> adequate depends on the quality of the seed, IIUC.) Both of these >>>>>>> issues don't apply specifically to a default RNG type that cannot be >>>>>>> initialized and always uses entropy from the global pool, but that's >>>>>>> not enough to vindicate the design, IMO. By emphasizing *which* RNG >>>>>>> instance is being used for random number generation, the design >>>>>>> encourages non-reuse of non-default RNGs, which is precisely where this >>>>>>> common error matters for performance (and maybe security). >>>>>>> >>>>>>> Maybe we call the default RNG instance `random`, and then give the >>>>>>> `random(in:)` methods another name, like `choose(in:)`? >>>>>>> >>>>>>> let diceRoll = random.choose(in: 1...6) >>>>>>> let card = random.choose(in: deck) >>>>>>> let isHeads = random.choose(in: [true, false]) >>>>>>> let probability = random.choose(in: 0.0...1.0) >>>>>>> let diceRoll = rng.choose(in: 1...6) >>>>>>> let card = rng.choose(in: deck) >>>>>>> let isHeads = rng.choose(in: [true, false]) >>>>>>> let probability = rng.choose(in: 0.0...1.0) >>>>>>> >>>>>>> This would allow us to keep the default RNG's type private and expose >>>>>>> it only as an existential—which means more code will treat RNGs as >>>>>>> black boxes, and people will extend the RNG protocol instead of the >>>>>>> default RNG struct—while also putting our default random number >>>>>>> generator under the name `random`, which is probably where people will >>>>>>> look for such a thing. >>>>>>> >>>>>>> I've said this already in my feedback, but it can get lost in the long >>>>>>> chain of replies, so I'll repeat myself here because it's relevant to >>>>>>> the discussion. I think one of the major difficulties of discussing the >>>>>>> proposed design is that Alejandro has chosen to use a property called >>>>>>> "random" to name multiple distinct functions which have distinct names >>>>>>> in other languages. In fact, almost every method or function is being >>>>>>> named "random." We are tripping over ourselves and muddling our >>>>>>> thinking (or at least, I find myself doing so) because different things >>>>>>> have the exact same name, and if I'm having this trouble after deep >>>>>>> study of the design, I think it's a good sign that this is going to be >>>>>>> greatly confusing to users generally. >>>>>>> >>>>>>> First, there's Alejandro's _static random_, which he proposes to return >>>>>>> an instance of type T given a type T. In Python, this is named >>>>>>> `randint(a, b)` for integers, and `random` (between 0 and 1) or >>>>>>> `uniform(a, b)` for floating-type types. The distinct names reflect the >>>>>>> fact that `randint` and `uniform` are mathematically quite different >>>>>>> (one samples a *discrete* uniform distribution and the other a >>>>>>> *continuous* uniform distribution), and I'm not aware of non-numeric >>>>>>> types offering a similar API in Python. These distinct names accurately >>>>>>> reflect critiques from others on this list that the proposed protocol >>>>>>> `Randomizable` lumps together types that don't share any common >>>>>>> semantics for their _static random_ method, and that the protocol is of >>>>>>> questionable utility because types in general do not share sufficient >>>>>>> semantics such that one can do interesting work in generic code with >>>>>>> such a protocol. >>>>>>> >>>>>>> Then there's Alejandro's _instance random_, which he proposes to return >>>>>>> an element of type T given a instance of a collection of type T. In >>>>>>> Python, this is named "choice(seq)" (for one element, or else throws an >>>>>>> error) and "sample(seq, k)" (for up to k elements). As I noted, >>>>>>> Alejandro was right to draw an analogy between _instance random_ and >>>>>>> other instance properties of a Collection such as `first` and `last`. >>>>>>> In fact, the behavior of Python's "choice" (if modified to return an >>>>>>> Optional) and "sample", as a pair, would fit in very well next to >>>>>>> Swift's existing pairs of `first` and `prefix(k)` and `last` and >>>>>>> `suffix(k)`. We could trivially Swiftify the names here; for example: >>>>>>> >>>>>>> ``` >>>>>>> [1, 2, 3].first >>>>>>> [1, 2, 3].any // or `choice`, or `some`, or... >>>>>>> [1, 2, 3].last >>>>>>> >>>>>>> [1, 2, 3].prefix(2) >>>>>>> [1, 2, 3].sample(2) >>>>>>> [1, 2, 3].suffix(2) >>>>>>> ``` >>>>>>> >>>>>>> I'm going to advocate again for _not_ naming all of these distinct >>>>>>> things "random". Even in conducting this discussion, it's so hard to >>>>>>> keep track of what particular function a person is giving feedback >>>>>>> about. >>>>>>> >>>>>>> >>>>>> >>>>>>> _______________________________________________ >>>>>>> swift-evolution mailing list >>>>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>>>> >>>>> On Nov 17, 2017, 8:32 PM -0600, Xiaodi Wu via swift-evolution >>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>, wrote: >>>>> >>>>>> On Fri, Nov 17, 2017 at 7:11 PM, Brent Royal-Gordon >>>>>> <br...@architechies.com <mailto:br...@architechies.com>> wrote: >>>>>>> On Nov 17, 2017, at 3:09 PM, Xiaodi Wu via swift-evolution >>>>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>>>>>> >>>>>>> But actually, Int.random followed by % is the much bigger issue and a >>>>>>> very good cautionary tale for why T.random is not a good idea. Swift >>>>>>> should help users do the correct thing, and getting a random value >>>>>>> across the full domain and computing an integer modulus is never the >>>>>>> correct thing to do because of modulo bias, yet it's a very common >>>>>>> error to make. We are much better off eliminating this API and >>>>>>> encouraging use of the correct API, thereby reducing the likelihood of >>>>>>> users making this category of error. >>>>>> >>>>>> Amen. >>>>>> >>>>>>> If (and I agree with this) the range-based notation is less intuitive >>>>>>> (0..<10.random is certainly less discoverable than Int.random), then we >>>>>>> ought to offer an API in the form of `Int.random(in:)` but not >>>>>>> `Int.random`. This does not preclude a `Collection.random` API as >>>>>>> Alejandro proposes, of course, and that has independent value as >>>>>>> Gwendal says. >>>>>> >>>>>> >>>>>> If we're not happy with the range syntax, maybe we should put >>>>>> `random(in:)`-style methods on the RNG protocol as extension methods >>>>>> instead. Then there's a nice, uniform style: >>>>>> >>>>>> let diceRoll = rng.random(in: 1...6) >>>>>> let card = rng.random(in: deck) >>>>>> let isHeads = rng.random(in: [true, false]) >>>>>> let probability = rng.random(in: 0.0...1.0) >>>>>> >>>>>> // Special FloatingPoint overload >>>>>> >>>>>> The only issue is that this makes the default RNG's name really >>>>>> important. Something like: >>>>>> >>>>>> DefaultRandom.shared.random(in: 1...6) >>>>>> >>>>>> Will be a bit of a pain for users. >>>>>> >>>>>> I did in fact implement this style of RNG in NumericAnnex, but I'm not >>>>>> satisfied with the design myself. Not only is it a bit of an ergonomic >>>>>> thorn, there's also another drawback that actually has weighty >>>>>> implications: >>>>>> >>>>>> Users aren't conditioned to reuse RNG instances. Perhaps, it is because >>>>>> it can "feel" wrong that multiple random instances should come from the >>>>>> *same* RNG. Instead, it "feels" more right to initialize a new RNG for >>>>>> every random number. After all, if one RNG is random, two must be >>>>>> randomer! This error is seen with some frequency in other languages that >>>>>> adopt this design, and they sometimes resort to educating users through >>>>>> documentation that isn't consistently heeded. >>>>>> >>>>>> Of course, you and I both know that this is not ideal for performance. >>>>>> Moreover, for a number of PRNG algorithms, the first few hundred or >>>>>> thousand iterations can be more predictable than later iterations. (Some >>>>>> algorithms discard the first n iterations, but whether that's adequate >>>>>> depends on the quality of the seed, IIUC.) Both of these issues don't >>>>>> apply specifically to a default RNG type that cannot be initialized and >>>>>> always uses entropy from the global pool, but that's not enough to >>>>>> vindicate the design, IMO. By emphasizing *which* RNG instance is being >>>>>> used for random number generation, the design encourages non-reuse of >>>>>> non-default RNGs, which is precisely where this common error matters for >>>>>> performance (and maybe security). >>>>>> >>>>>> Maybe we call the default RNG instance `random`, and then give the >>>>>> `random(in:)` methods another name, like `choose(in:)`? >>>>>> >>>>>> let diceRoll = random.choose(in: 1...6) >>>>>> let card = random.choose(in: deck) >>>>>> let isHeads = random.choose(in: [true, false]) >>>>>> let probability = random.choose(in: 0.0...1.0) >>>>>> let diceRoll = rng.choose(in: 1...6) >>>>>> let card = rng.choose(in: deck) >>>>>> let isHeads = rng.choose(in: [true, false]) >>>>>> let probability = rng.choose(in: 0.0...1.0) >>>>>> >>>>>> This would allow us to keep the default RNG's type private and expose it >>>>>> only as an existential—which means more code will treat RNGs as black >>>>>> boxes, and people will extend the RNG protocol instead of the default >>>>>> RNG struct—while also putting our default random number generator under >>>>>> the name `random`, which is probably where people will look for such a >>>>>> thing. >>>>>> >>>>>> I've said this already in my feedback, but it can get lost in the long >>>>>> chain of replies, so I'll repeat myself here because it's relevant to >>>>>> the discussion. I think one of the major difficulties of discussing the >>>>>> proposed design is that Alejandro has chosen to use a property called >>>>>> "random" to name multiple distinct functions which have distinct names >>>>>> in other languages. In fact, almost every method or function is being >>>>>> named "random." We are tripping over ourselves and muddling our thinking >>>>>> (or at least, I find myself doing so) because different things have the >>>>>> exact same name, and if I'm having this trouble after deep study of the >>>>>> design, I think it's a good sign that this is going to be greatly >>>>>> confusing to users generally. >>>>>> >>>>>> First, there's Alejandro's _static random_, which he proposes to return >>>>>> an instance of type T given a type T. In Python, this is named >>>>>> `randint(a, b)` for integers, and `random` (between 0 and 1) or >>>>>> `uniform(a, b)` for floating-type types. The distinct names reflect the >>>>>> fact that `randint` and `uniform` are mathematically quite different >>>>>> (one samples a *discrete* uniform distribution and the other a >>>>>> *continuous* uniform distribution), and I'm not aware of non-numeric >>>>>> types offering a similar API in Python. These distinct names accurately >>>>>> reflect critiques from others on this list that the proposed protocol >>>>>> `Randomizable` lumps together types that don't share any common >>>>>> semantics for their _static random_ method, and that the protocol is of >>>>>> questionable utility because types in general do not share sufficient >>>>>> semantics such that one can do interesting work in generic code with >>>>>> such a protocol. >>>>>> >>>>>> Then there's Alejandro's _instance random_, which he proposes to return >>>>>> an element of type T given a instance of a collection of type T. In >>>>>> Python, this is named "choice(seq)" (for one element, or else throws an >>>>>> error) and "sample(seq, k)" (for up to k elements). As I noted, >>>>>> Alejandro was right to draw an analogy between _instance random_ and >>>>>> other instance properties of a Collection such as `first` and `last`. In >>>>>> fact, the behavior of Python's "choice" (if modified to return an >>>>>> Optional) and "sample", as a pair, would fit in very well next to >>>>>> Swift's existing pairs of `first` and `prefix(k)` and `last` and >>>>>> `suffix(k)`. We could trivially Swiftify the names here; for example: >>>>>> >>>>>> ``` >>>>>> [1, 2, 3].first >>>>>> [1, 2, 3].any // or `choice`, or `some`, or... >>>>>> [1, 2, 3].last >>>>>> >>>>>> [1, 2, 3].prefix(2) >>>>>> [1, 2, 3].sample(2) >>>>>> [1, 2, 3].suffix(2) >>>>>> ``` >>>>>> >>>>>> I'm going to advocate again for _not_ naming all of these distinct >>>>>> things "random". Even in conducting this discussion, it's so hard to >>>>>> keep track of what particular function a person is giving feedback about. >>>>>> >>>>>> >>>>> >>>>>> _______________________________________________ >>>>>> swift-evolution mailing list >>>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>>>> >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> <https://lists.swift.org/mailman/listinfo/swift-evolution> > > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org <mailto:swift-evolution@swift.org> > https://lists.swift.org/mailman/listinfo/swift-evolution > <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution