<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><span></span></div><div><div>On Jan 12, 2018, at 6:24 PM, Jonathan Hull via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=utf-8"><div class="">I think we have different definitions of consistency. I am fine with the ergonomics of (0…100).random() as a convenience, but it really worries me here that everything is special cased. Special cased things are fine for individual projects, but not the standard library. We should make sure that the design is flexible and extensible, and that comes in part from having a consistent interface.</div><div class=""><br class=""></div><div class="">Also, as I said before, we really shouldn’t be doing these crazy contortions to avoid ‘random() % 100’. Instead we should look for that pattern and issue with a warning + fixit to change it to random(in:). I think that will be much more effective in actually changing the behavior in the long run.</div></div></blockquote><div><br></div><div>I’m not sure what contortions you’re describing—from what I’ve seen, the proposal author is going to revise the proposal to have these ways of generating individual values:</div><div><br></div><div>In extensions to FixedWidthInteger and BinaryFloatingPoint:</div><div>static func random(in: Range/ClosedRange<Self>, using: RandomNumberGenerator) -> Self</div><div><br></div><div>In an extension to Bool:</div><div>static func random(using: RandomNumberGenerator) -> Self</div><div><br></div><div>If someone still needs a full-width random value as a building-block for generating random instances of other types, they should use the `next()` method directly on a RandomNumberGenerator. In the example code you sent, you could switch to using a RandomNumberGenerator instead of your RandomSourceValue, or base your RandomSourceValue generation on a RandomNumberGenerator instead of whatever random generator you’re using now.</div><div><br></div><blockquote type="cite"><div><div class="">Finally, tying everything to Range is extremely limiting. I understand if we don’t want to add other types to the standard library, but I should be able to build on what we add to do it myself without having to reinvent the wheel for each type. It is important to have a consistent story for these things (including multi-dimensional types) so that they can interoperate.</div></div></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"><div><div class="">We really should be looking at GamePlayKit more for design inspiration. There are several use-cases there that are being blatantly ignored in this discussion. For example, what if I want to randomly generate a game world (e.g. The square from The Battle For Polytopia” formerly “SuperTribes”)? Or what if I want an effect where it randomly fades in letters from a String. (…).random() will be completely inadequate for these things.</div></div></blockquote><div><br></div><div>The goal at this point is to build into the standard library the basis for all kinds of other use cases. Your library is one such example of something that can be built on top of the protocol and methods that are being proposed, as are a variety of other tasks, as I tried to show in the playground.</div><div><br></div><div>What’s being proposed now is deliberately short of solving every need—the additions would handle the hard stuff (correct and safe generation of integers and floating-points, along with shuffling collections) and lay the groundwork for other libraries to take things farther (by establishing the RandomNumberGenerator, a default generator, and a pattern for their use).</div><div><br></div><div>Speaking of GameplayKit, you can make GKRandomSource conform to RandomNumberGenerator in an extension, making all the GK... sources generators. If you’re already depending on those random sources, you’d still have access to them with the proposed model.</div><div><br></div><div>Nate</div><br><blockquote type="cite"><div><div class="">Thanks,</div><div class="">Jon</div><div class=""><br class=""></div><div class=""><br class=""></div><br class=""><div><blockquote type="cite" class=""><div class="">On Jan 12, 2018, at 5:11 AM, Letanyan Arumugam <<a href="mailto:letanyan.a@gmail.com" class="">letanyan.a@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">Nate’s design follows a consistent idea of getting a random value from some set of values. Adding the static method random() to a type essentially creates an implicit set which you yourself said leads to inconsistency (Double/Int). Secondly I don’t see why random(in:) should be added when it is just a different spelling for what is already provided. If my second statement is incorrect and there’s something I’m missing please correct me?</div><div class=""><br class=""></div><div class="">I think that consistency outweighs the random trapping inconsistency, however I would actually be fine if random returned an optional. Though the way random is used would likely lead to less opportunities for a trap than the other methods you mention. </div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Letanyan</div><div class=""><br class=""><blockquote type="cite" class=""><div class="">On 12 Jan 2018, at 04:39, Alejandro Alonso <<a href="mailto:aalonso128@outlook.com" class="">aalonso128@outlook.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class="">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" class="">
<title class=""></title>
<div class="">
<div name="messageBodySection" style="font-size: 14px; font-family: -apple-system, BlinkMacSystemFont, sans-serif;" class="">
If anything, Nate’s design is inconsistent as properties like `.first` and `.last` return an optional, and methods like `.min()` and `.max()` return an optional as well. Having `.random()` on ranges be an exception and return non optionals are inconsistent
with other collection facilities, and with other collections that aren’t ranges that return optionals on `.random()`.</div>
<div name="messageSignatureSection" style="font-size: 14px; font-family: -apple-system, BlinkMacSystemFont, sans-serif;" class="">
<br class="">
- Alejandro</div>
<div name="messageReplySection" style="font-size: 14px; font-family: -apple-system, BlinkMacSystemFont, sans-serif;" class="">
<br class="">
On Jan 11, 2018, 12:06 PM -0600, Letanyan Arumugam via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>>, wrote:<br class="">
<blockquote type="cite" style="margin: 5px 5px; padding-left: 10px; border-left: thin solid #1abc9c;" class="">
<div class="">This is really cool and seems very powerful. However I don’t think we should sacrifice consistency for extendability. Especially when the extendability would not be what most people need. </div>
<div class=""><br class="">
</div>
<div class="">What I am basically trying to say is that. I think the proposals current design direction fits better in a Random library rather than the Standard Library. And Nate’s design more directly addresses the motivating points of the proposal.</div>
<div class=""><br class="">
</div>
<div class="">Letanyan</div>
<div class=""><br class="">
</div>
<div class="">
<blockquote type="cite" class="" style="margin: 5px 5px; padding-left: 10px; border-left: thin solid #e67e22;">
<div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">
<br class="">
<div class="">Sure. Small disclaimer that this was originally written back in the Swift 1~2 days, so it is overdue for a simplifying rewrite.</div>
<div class=""><br class="">
</div>
<div class="">Also, I should point out that the term “Source” has a special meaning in my code. It basically means that something will provide an ~infinite collection of values of a type T. I have what I call a “ConstantSource” which just wraps a T and gives
it back when asked. But then I have a bunch of other “sources" which let you create repeating patterns and do deferred calculations and things like that. Finally I have a “RandomSource” which is part of what started this discussion. You set up a RandomSource
with a set of constraints, and then it gives you random values of T that adhere to those constraints (e.g. colors with a range of hues but the same saturation) whenever you ask for them.</div>
<div class=""><br class="">
</div>
<div class="">This is really useful for doing things like graphic effects because, for example, I can ask for a source of colors and a source of line widths and then get out a large variety of interesting patterns from the same algorithm. I can make simple
stripes with ConstantSources, or I can make repeating patterns of lines with repeating sources, or I can have random colors which look good together by using a RandomSource. I can take a BezierPath and make it look hand-drawn by breaking it into a bunch of
lines and then offset the points a small amount using a RandomSource of CGVectors.</div>
<div class=""><br class="">
</div>
<div class="">
<div class="">Not sure how useful this concept of randomness (and pattern) is to others, but I find it immensely useful! Not sure of the best way to implement it. The way I do it is a type erased protocol with private conforming structs and then public initializers
on the type-erasing box. The end result is that I can just say:</div>
<div class=""><br class="">
</div>
<div class=""><span class="Apple-tab-span" style="white-space: pre;"></span>let myConst = Source(1) //ConstantSource with 1 as a value</div>
<div class=""><span class="Apple-tab-span" style="white-space: pre;"></span>let myPattern = Source([1, 2]) //OrderedSource which repeats 1, then 2 over and over forever</div>
<div class=""><span class="Apple-tab-span" style="white-space: pre;"></span>let myMeta = Source([myConst, myPattern]) //Will alternate between sub-sources in order. Can be nested.</div>
<div class=""><span class="Apple-tab-span" style="white-space: pre;"></span>//…and so on.</div>
<div class=""><br class="">
</div>
<div class="">It is quite extensible and can make very complex/interesting patterns very easily. What I like about it is that (well controlled) random values and patterns or constant values can be interchanged very easily.</div>
</div>
<div class=""><br class="">
</div>
<div class="">The RandomSource has a RandomSourceCreatable Protocol that lets it take random bits and turn them into objects/structs of T adhering to the given constraints. This is way more complex under the hood than it needs to be, but it works well in practice,
and I haven’t gotten around to cleaning it up yet:</div>
<div class=""><br class="">
</div>
<div class=""><span class="Apple-tab-span" style="white-space:pre"></span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(4, 51, 255);" class="">public</span>
<span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">
</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(4, 51, 255);" class="">protocol</span>
<span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">
RandomSourceCreatable {</span></div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span><span style="color: #0433ff" class="">associatedtype</span> ConstraintType =
<span style="color: #0433ff" class="">Self</span></div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255); min-height: 13px;" class="">
<br class="webkit-block-placeholder">
</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 128, 0); background-color: rgb(255, 255, 255);" class="">
<span style="" class=""> <span class="Apple-tab-span" style="white-space:pre">
</span></span>///This should be implimented by simple types without internal components</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(52, 149, 175); background-color: rgb(255, 255, 255);" class="">
<span style="" class=""> <span class="Apple-tab-span" style="white-space:pre">
</span></span><span style="color: #0433ff" class="">static</span> <span style="" class="">
</span><span style="color: #0433ff" class="">func</span> <span style="" class="">
createRandom(rnd value:</span>RandomSourceValue<span style="" class="">, constraint:</span>RandomSourceConstraint<span style="" class=""><</span>ConstraintType<span style="" class="">>)-></span>Self</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255); min-height: 13px;" class="">
<br class="webkit-block-placeholder">
</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 128, 0); background-color: rgb(255, 255, 255);" class="">
<span style="" class=""><span class="Apple-tab-span" style="white-space:pre"></span></span>///This should be implimented by complex types with multiple axis of constraints</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(52, 149, 175); background-color: rgb(255, 255, 255);" class="">
<span style="" class=""> <span class="Apple-tab-span" style="white-space:pre">
</span></span><span style="color: #0433ff" class="">static</span> <span style="" class="">
</span><span style="color: #0433ff" class="">func</span> <span style="" class="">
createRandom(rnd value:</span>RandomSourceValue<span style="" class="">, constraints:[</span>String<span style="" class="">:</span>RandomSourceConstraint<span style="" class=""><</span>ConstraintType<span style="" class="">>])-></span>Self</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255); min-height: 13px;" class="">
<br class="webkit-block-placeholder">
</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 128, 0); background-color: rgb(255, 255, 255);" class="">
<span style="" class=""> <span class="Apple-tab-span" style="white-space:pre">
</span></span>///Returns the proper dimension for the type given the constraints</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(52, 149, 175); background-color: rgb(255, 255, 255);" class="">
<span style="" class=""> <span class="Apple-tab-span" style="white-space:pre">
</span></span><span style="color: #0433ff" class="">static</span> <span style="" class="">
</span><span style="color: #0433ff" class="">func</span> <span style="" class="">
dimension(given contraints:[</span>String<span style="" class="">:</span>RandomSourceConstraint<span style="" class=""><</span>ConstraintType<span style="" class="">>])-></span>RandomSourceDimension</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255); min-height: 13px;" class="">
<br class="webkit-block-placeholder">
</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 128, 0); background-color: rgb(255, 255, 255);" class="">
<span style="" class=""> <span class="Apple-tab-span" style="white-space:pre">
</span></span>///Validates the given contraints to make sure they can create valid objects. Only needs to be overridden for extremely complex types</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span><span style="color: #0433ff" class="">static</span>
<span style="color: #0433ff" class="">func</span> validateConstraints(<span style="color: #0433ff" class="">_</span> constraints:[<span style="color: #3495af" class="">String</span>:<span style="color: #3495af" class="">RandomSourceConstraint</span><<span style="color: #3495af" class="">ConstraintType</span>>])-><span style="color: #3495af" class="">Bool</span></div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255); min-height: 13px;" class="">
<br class="webkit-block-placeholder">
</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 128, 0); background-color: rgb(255, 255, 255);" class="">
<span style="" class=""> <span class="Apple-tab-span" style="white-space:pre">
</span></span>///Convienience method which provides whitelist of keys for implicit validation of constraints</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span><span style="color: #0433ff" class="">static</span>
<span style="color: #0433ff" class="">var</span> allowedConstraintKeys:<span style="color: #3495af" class="">Set</span><<span style="color: #3495af" class="">String</span>> {<span style="color: #0433ff" class="">get</span>}</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
}</div>
<div class=""><br class="">
</div>
<div class="">Most of these things also have default implementations so you only really have to deal with them for complex cases like colors or points. The constraints are given using a dictionary with string keys and a RandomSourceConstraint value, which
is defined like this:</div>
<div class=""><br class="">
</div>
<div class=""><span class="Apple-tab-span" style="white-space:pre"></span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(4, 51, 255);" class="">public</span>
<span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">
</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(4, 51, 255);" class="">enum</span>
<span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">
RandomSourceConstraint<T> {</span></div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span><span style="color: #0433ff" class="">case</span> none</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span><span style="color: #0433ff" class="">case</span> constant(<span style="color: #3495af" class="">T</span>)</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span><span style="color: #0433ff" class="">case</span> min(<span style="color: #3495af" class="">T</span>)</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span><span style="color: #0433ff" class="">case</span> max(<span style="color: #3495af" class="">T</span>)</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span><span style="color: #0433ff" class="">case</span> range (<span style="color: #3495af" class="">T</span>,<span style="color: #3495af" class="">T</span>)</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span><span style="color: #0433ff" class="">case</span> custom ( (<span style="color: #3495af" class="">RandomSourceValue</span>)-><span style="color: #3495af" class="">T</span> )</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span></div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span>//A bunch of boring convenience code here that transforms values so I don’t always have to switch on the enum in other code that deals with this. I just ask for the bounds or constrained T (Note: T
here refers to the type for a single axis as opposed to the generated type. e.g. CGFloat for a point) </div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
}</div>
<div class=""><br class="">
</div>
<div class="">I have found that this handles pretty much all of the constraints I need, and the custom constraint is useful for anything exotic (e.g. sig-figs). The RandomSource itself has convenience inits when T is Comparable that let you specify a range
instead of having to create the constraints yourself.</div>
<div class=""><br class="">
</div>
<div class="">I then have conformed many standard types to RandomSourceCreatable so that I can create Sources out of them. Here is CGPoint for reference:</div>
<div class=""><br class="">
</div>
<div class=""><span class="Apple-tab-span" style="white-space:pre"></span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(4, 51, 255);" class="">extension</span>
<span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">
</span><span style="color: rgb(52, 149, 175); font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">CGPoint</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">:</span><span style="color: rgb(52, 149, 175); font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">RandomSourceCreatable</span>
<span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">
{</span></div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255); min-height: 13px;" class="">
<br class="webkit-block-placeholder">
</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(52, 149, 175); background-color: rgb(255, 255, 255);" class="">
<span style="" class=""> <span class="Apple-tab-span" style="white-space:pre">
</span></span><span style="color: #0433ff" class="">public</span> <span style="" class="">
</span><span style="color: #0433ff" class="">static</span> <span style="" class="">
</span><span style="color: #0433ff" class="">func</span> <span style="" class="">
dimension(given contraints:[</span>String<span style="" class="">:</span>RandomSourceConstraint<span style="" class=""><</span>CGFloat<span style="" class="">>])-></span>RandomSourceDimension
<span style="" class="">{</span></div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(52, 149, 175); background-color: rgb(255, 255, 255);" class="">
<span style="" class=""> <span class="Apple-tab-span" style="white-space:pre">
</span></span><span style="color: #0433ff" class="">return</span> <span style="" class="">
</span>RandomSourceDimension<span style="" class="">.</span>manyWord<span style="" class="">(2)</span></div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span>}</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255); min-height: 13px;" class="">
<br class="webkit-block-placeholder">
</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span><span style="color: #0433ff" class="">public</span>
<span style="color: #0433ff" class="">typealias</span> ConstraintType = <span style="color: #3495af" class="">
CGFloat</span></div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span><span style="color: #0433ff" class="">public</span>
<span style="color: #0433ff" class="">static</span> <span style="color: #0433ff" class="">
var</span> allowedConstraintKeys:<span style="color: #3495af" class="">Set</span><<span style="color: #3495af" class="">String</span>>{</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span><span style="color: #0433ff" class="">return</span> [<span style="color: #b4261a" class="">"x"</span>,<span style="color: #b4261a" class="">"y"</span>]</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span>}</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255); min-height: 13px;" class="">
<br class="webkit-block-placeholder">
</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(52, 149, 175); background-color: rgb(255, 255, 255);" class="">
<span style="" class=""> <span class="Apple-tab-span" style="white-space:pre">
</span></span><span style="color: #0433ff" class="">public</span> <span style="" class="">
</span><span style="color: #0433ff" class="">static</span> <span style="" class="">
</span><span style="color: #0433ff" class="">func</span> <span style="" class="">
createRandom(rnd value:</span>RandomSourceValue<span style="" class="">, constraints:[</span>String<span style="" class="">:</span>RandomSourceConstraint<span style="" class=""><</span>CGFloat<span style="" class="">>])-></span>CGPoint
<span style="" class="">{</span></div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span><span style="color: #0433ff" class="">let</span> xVal = value.<span style="color: #3495af" class="">value</span>(at: 0)</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span><span style="color: #0433ff" class="">let</span> yVal = value.<span style="color: #3495af" class="">value</span>(at: 1)</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 143, 0); background-color: rgb(255, 255, 255);" class="">
<span style="" class=""> <span class="Apple-tab-span" style="white-space:pre">
</span></span>//Note: Ints have a better distribution for normal use cases of points</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span><span style="color: #0433ff" class="">let</span> x =
<span style="color: #3495af" class="">CGFloat</span>(<span style="color: #3495af" class="">Int</span>.<span style="color: #3495af" class="">createRandom</span>(rnd: xVal, constraint: constraints[<span style="color: #b4261a" class="">"x"</span>]?.<span style="color: #3495af" class="">asType</span>({<span style="color: #3495af" class="">Int</span>($0
* 1000)}) ?? .<span style="color: #3495af" class="">none</span>))/1000</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span><span style="color: #0433ff" class="">let</span> y =
<span style="color: #3495af" class="">CGFloat</span>(<span style="color: #3495af" class="">Int</span>.<span style="color: #3495af" class="">createRandom</span>(rnd: yVal, constraint: constraints[<span style="color: #b4261a" class="">"y"</span>]?.<span style="color: #3495af" class="">asType</span>({<span style="color: #3495af" class="">Int</span>($0
* 1000)}) ?? .<span style="color: #3495af" class="">none</span>))/1000</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span><span style="color: #0433ff" class="">return</span>
<span style="color: #3495af" class="">CGPoint</span>(x: x, y: y)</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span class="Apple-tab-span" style="white-space:pre"></span>}</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
}</div>
<div class=""><br class="">
</div>
<div class="">Notice that I have a RandomSourceValue type that provides the random bits of the requested dimension. When I get around to updating this, I might do something closer to the proposal, where I would just pass the generator and grab bits as needed.
The main reason I did it the way I did is that it lets me have random access to the source very easily. </div>
<div class=""><br class="">
</div>
<div class="">The ‘asType’ method converts a constraint to work with another type (in this case Ints).</div>
<div class=""><br class="">
</div>
<div class="">Colors are a bit more complicated, mainly because I allow a bunch of different constraints, and I also have validation code to make sure the constraints fit together properly. I also ask for different amounts of randomness based on whether it
is greyscale or contains alpha. Just to give you a sense, here are the allowed constraint keys for a CGColor:</div>
<div class=""><span class="Apple-tab-span" style="white-space:pre"></span></div>
<div class=""><span class="Apple-tab-span" style="white-space:pre"></span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(4, 51, 255);" class="">public</span>
<span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">
</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(4, 51, 255);" class="">static</span>
<span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">
</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(4, 51, 255);" class="">var</span>
<span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">
allowedConstraintKeys:</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(52, 149, 175);" class="">Set</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class=""><</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(52, 149, 175);" class="">String</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">>{</span></div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(180, 38, 26); background-color: rgb(255, 255, 255);" class="">
<span style="" class=""> </span> <span style="color: #0433ff" class="">return</span>
<span style="" class="">[</span>"alpha"<span style="" class="">,</span>"gray"<span style="" class="">,</span>"red"<span style="" class="">,</span>"green"<span style="" class="">,</span>"blue"<span style="" class="">,</span> "hue"<span style="" class="">,</span>
"saturation"<span style="" class="">,</span> "brightness"<span style="" class="">]</span></div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
}</div>
<div class=""><br class="">
</div>
<div class="">and here is the creation method when the keys are for RGBA (I have similar sections for HSBA and greyscale):</div>
<div class=""><br class="">
</div>
<div class=""><span class="Apple-tab-span" style="white-space:pre"></span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(4, 51, 255);" class="">let</span>
<span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">
rVal = value.</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(52, 149, 175);" class="">value</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">(at:
0)</span></div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span style="color: #0433ff" class="">let</span> gVal = value.<span style="color: #3495af" class="">value</span>(at: 1)</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span style="color: #0433ff" class="">let</span> bVal = value.<span style="color: #3495af" class="">value</span>(at: 2)</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span style="color: #0433ff" class="">let</span> aVal = value.<span style="color: #3495af" class="">value</span>(at: 3)</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span style="color: #0433ff" class="">let</span> r = <span style="color: #3495af" class="">
CGFloat</span>.<span style="color: #3495af" class="">createRandom</span>(rnd: rVal, constraint: constraints[<span style="color: #b4261a" class="">"red"</span>] ?? .<span style="color: #3495af" class="">range</span>(0,1))</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span style="color: #0433ff" class="">let</span> g = <span style="color: #3495af" class="">
CGFloat</span>.<span style="color: #3495af" class="">createRandom</span>(rnd: gVal, constraint: constraints[<span style="color: #b4261a" class="">"green"</span>] ?? .<span style="color: #3495af" class="">range</span>(0,1))</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span style="color: #0433ff" class="">let</span> b = <span style="color: #3495af" class="">
CGFloat</span>.<span style="color: #3495af" class="">createRandom</span>(rnd: bVal, constraint: constraints[<span style="color: #b4261a" class="">"blue"</span>] ?? .<span style="color: #3495af" class="">range</span>(0,1))</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span style="color: #0433ff" class="">let</span> a = <span style="color: #3495af" class="">
CGFloat</span>.<span style="color: #3495af" class="">createRandom</span>(rnd: aVal, constraint: constraints[<span style="color: #b4261a" class="">"alpha"</span>] ?? .<span style="color: #3495af" class="">constant</span>(1.0))</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255); min-height: 13px;" class="">
<br class="webkit-block-placeholder">
</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<span style="color: #0433ff" class="">return</span> <span style="color: #0433ff" class="">
self</span>.<span style="color: #0433ff" class="">init</span>(colorSpace: <span style="color: #3495af" class="">
CGColorSpaceCreateDeviceRGB</span>(), components: [r,g,b,a])!</div>
<div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">
<br class="">
</div>
<div class=""><br class="">
</div>
<div class="">The end result is that initializing a source of CGColors looks like this (either parameter can be omitted if desired):</div>
<div class=""><br class="">
</div>
<div class=""><span class="Apple-tab-span" style="white-space:pre"></span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(4, 51, 255);" class="">let</span>
<span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">
colorSource:</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(52, 149, 175);" class="">Source</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class=""><</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); text-decoration: underline; color: rgb(52, 149, 175);" class="">C</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(52, 149, 175);" class="">GColor</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">>
= </span><span style="color: rgb(52, 149, 175); font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">Source</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">(seed: optionalSeed,
constraints:[</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(180, 38, 26);" class="">"saturation"</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">:
.constant(0.4),</span> <span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(180, 38, 26);" class="">
"brightness"</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">: .constant(0.6)])</span></div>
<div class=""><br class="">
</div>
<div class="">Anyway, I hope this was useful/informative. I know the code is a bit messy, but I still find it enormously useful in practice. I plan to clean it up when I find time, simplifying the RandomSourceValue stuff and moving from String Keys to a Struct
with static functions for the constraints. The new constraints will probably end up looking like this:</div>
<div class=""><br class="">
</div>
<div class=""><span class="Apple-tab-span" style="white-space:pre"></span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(4, 51, 255);" class="">let</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class=""> colorSource:</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(52, 149, 175);" class="">Source</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class=""><</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); text-decoration: underline; color: rgb(52, 149, 175);" class="">C</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255); color: rgb(52, 149, 175);" class="">GColor</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">>
= </span><span style="color: rgb(52, 149, 175); font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">Source</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">(seed: optionalSeed,
constraints:[</span><span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">.saturation(0.4), </span><span style="background-color: rgb(255, 255, 255);" class=""><font face="Menlo" class=""><span style="font-size: 11px;" class="">.brightness(0.4...0.6)])</span></font></span></div>
<div class=""><br class="">
</div>
<div class="">Thanks,</div>
<div class="">Jon</div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
</div>
_______________________________________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
</blockquote>
</div>
<br class="">
_______________________________________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
</blockquote>
</div>
</div>
</div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></div></body></html>