I have researched and looked into many different random function, but the downside to them is that they only work for one data type. I want a way to have one function work for a Double, Floats, Int, CGFloat, etc. I know I could just convert it to different data types, but I would like to know if there is a way to have it done using generics. Does someone know a way to make a generic random function using swift. Thanks.
In theory you could port code such as this answer (which is not necessarily a great solution, depending on your needs, since UInt32.max is relatively small)
extension FloatingPointType {
static func rand() -> Self {
let num = Self(arc4random())
let denom = Self(UInt32.max)
// this line won’t compile:
return num / denom
}
}
// then you could do
let d = Double.rand()
let f = Float.rand()
let c = CGFloat.rand()
Except… FloatingPointType doesn’t conform to a protocol that guarantees operators like /, + etc (unlike IntegerType which conforms to _IntegerArithmeticType).
You could do this manually though:
protocol FloatingPointArithmeticType: FloatingPointType {
func /(lhs: Self, rhs: Self) -> Self
// etc
}
extension Double: FloatingPointArithmeticType { }
extension Float: FloatingPointArithmeticType { }
extension CGFloat: FloatingPointArithmeticType { }
extension FloatingPointArithmeticType {
static func rand() -> Self {
// same as before
}
}
// so these now work
let d = Double.rand() // etc
but this probably isn’t quite as out-of-the-box as you were hoping (and no doubt contains some subtle invalid assumption about floating-point numbers on my part).
As for something that works across both integers and floats, the Swift team have mentioned on their mail groups before that the lack of protocols spanning both types is a conscious decision since it’s rarely correct to write the same code for both, and that’s certainly the case for generating random numbers, which need two very different approaches.
Before you get too far into this, think about what you want the behavior of a type-agnostic random function to be, and whether that's something that you want. It sounds like you're proposing something like this:
// signature only
func random<T>() -> T
// example call sites, with specialization by inference from declared result type
let randInt: Int = random()
let randFloat: Float = random()
let randDouble: Double = random()
let randInt64: Int = random()
(Note this syntax is sort of fake: without a parameter of type T, the implementation of random<T>() can't determine which type to return.)
What do you expect the possible values in each of these to be? Is randInt always a value between zero and Int.max? (Or maybe between zero and UInt32.max?) Is randFloat always between 0.0 and 1.0? Should randDouble actually have a larger count of possible values than randFloat (per the increased resolution between 0.0 and 1.0 of the Double type)? How do you account for the fact that Int is actually Int32 on 32-bit systems and Int64 on 64-bit hardware?
Are you sure it makes sense to have two (or more) calls that look identical but return values in different ranges?
Second, do you really want "arbitrarily random" random number generation everywhere in your app/game? Most use of RNGs is in game design, where typically there are a couple of important things you want in your RNG before you get your product past the prototyping stage:
Independence: I've seen games where you could learn to predict the next "random" enemy encounter based on recent "random" NPC chitchat/emotes. If you're using random elements in multiple gameplay systems, you don't want
Determinism: If you want to be able to reproduce a sequence of game events — either for testing/debugging or for consistent results between clients in a networked game — you don't want to be using a random function where you can't control that sequence. arc4random doesn't let you control the initial seed, and you have no control over the sequence because you don't know what other code in your process (library code, or just other code of your own that you forgot about) is also pulling numbers from the generator.
(If you're not making a game... much of this still applies, though it may be less important. You still don't want to be re-running your test case until the heat death of the universe trying to randomly find the same bug that one of your users reported.)
In iOS 9 / OS X 10.11 / tvOS, GameplayKit provides a suite of randomization tools to address these issues.
let randA = GKARC4RandomSource()
let someNumbers = (0..<1000).map { _ in randA.nextInt() }
let randB = GKARC4RandomSource()
let someMoreNumbers = (0..<1000).map { _ in randB.nextInt() }
let randC = GKARC4RandomSource(seed: randA.seed)
let evenMoreNumbers = (0..<1000).map { _ in randC.nextInt() }
Here, someMoreNumbers is always nondeterministic, no matter what happens in the generation of someNumbers or what other randomization activity happens on the system. And evenMoreNumbers is the exact same sequence of numbers as someNumbers.
Okay, so the GameplayKit syntax isn't quite what you want? Well, some of that is a natural consequence of having to manage RNGs as objects so that you can keep them independent and deterministic. But if you really want to have a super-simple random() call that you can slot in wherever needed, regardless of return type, and be independent and deterministic...
Here's one possible recipe for that. It implements random() as a static function on a type extension, so that you can use type-inference shorthand to write it; e.g.:
// func somethingThatTakesAnInt(a: Int, andAFloat Float: b)
somethingThatTakesAnInt(.random(), andAFloat: random())
The first parameter automatically calls Int.random() and the second calls Float.random(). (This is the same mechanism that lets you use shorthand for referring to enum cases, or .max instead of Int.max, etc.)
And it makes the type extensions private, with the idea that different source files will want independent RNGs.
// EnemyAI.swift
private extension Int {
static func random() -> Int {
return EnemyAI.die.nextInt()
}
}
class EnemyAI: NSObject {
static let die = GKARC4RandomSource()
// ...
}
// ProceduralWorld.swift
private extension Int {
static func random() -> Int {
return ProceduralWorld.die.nextInt()
}
}
class ProceduralWorld: NSObject {
static let die = GKARC4RandomSource()
// ...
}
Repeat with extensions for more types as desired.
If you add some breakpoints or logging to the different random() functions you'll see that the two implementations of Int.random() are specific to the file they're in.
Anyway, that's a lot of boilerplate, but perhaps it's good food for thought...
Personally, I'd probably write individual implementations for each thing you wanted. There just aren't that many, and it's a lot safer and more flexible. But… sure, you can do this. Just create a random bit pattern and say "that's a number."
func randomValueOfType<T>(type: T.Type) -> T {
let size = sizeof(type)
let bits = UnsafeMutablePointer<T>.alloc(1)
arc4random_buf(bits, size)
return bits.memory
}
(This is technically "that's a something" but if you pass it something other than number-like types, you'll probably crash because most random bit patterns aren't a legal object.)
I believe every possible bit pattern will generate a legal IEEE 754 number, but "legal" may be more complex than you're thinking. A "totally random" float would rightly include NaN (not-a-number) which will show up reasonably often in your results.
There are some other special cases like the infinities and negative zero, but in practice those should never occur. Any single bit pattern showing up in a random choice of 32-bits is effectively zero. There are lots of NaN bit patterns, so it shows up a lot.
And that's the problem with this whole approach. If your random generator can accept that NaN shows up, then it's probably testing real floating point. But if you're testing real floating point, you really want to be checking the edge cases like infinity and negative zero. But if you don't want to include NaN, then you don't really mean "a random Float" you mean "a random Real number that can be expressed as a Float." There's no type for that, so you would need to write specific logic to handle it, and if you're doing that, you might as well write a specialized random generator for each type.
But this function is probably still a useful foundation for building that. You could just generate values until one is a legal number (NaN doesn't show up that often, so you'll almost certainly get it in less than 2 tries).
This kind of emphasizes the point Airspeed Velocity made about why there's no generic "number" protocol. You usually can't just treat floating point numbers like integers. They just work differently, and you very often need to think about that fact.
Related
I am converting a program written in Pascal to Swift and some Pascal features do not have direct Swift equivalents such as variant records and defining sets as types. A variant record in Pascal enables you to assign different field types to the same area of memory in a record. In other words, one particular location in a record could be either of type A or of type B. This can be useful in either/or cases, where a record can have either one field or the other field, but not both. What are the Swift equivalents for a variant record and a set type like setty in the Pascal fragment?
The Pascal code fragment to be converted is:
const
strglgth = 16;
sethigh = 47;
setlow = 0;
type
setty = set of setlow..sethigh;
cstclass = (reel,pset,strg);
csp = ^constant; /* pointer to constant type */
constant = record case cclass: cstclass of
reel: (rval: packed array [1..strglgth] of char);
pset: (pval: setty);
strg: (slgth: 0..strglgth;
sval: packed array [1..strglgth] of char)
end;
var
lvp: csp
My partial Swift code is
let strglgth = 16
let sethigh = 47
let setlow = 0
enum cstclass : Int {case reel = 0, pset, strg}
var lvp: csp
Any advice is appreciated. Thanks in advance.
Variant records in Pascal are very simular to unions in C.
So this link will probably be helpful:
https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/using_imported_c_structs_and_unions_in_swift
In case the link ever goes dead, here's the relevant example:
union SchroedingersCat {
bool isAlive;
bool isDead;
};
In Swift, it’s imported like this:
struct SchroedingersCat {
var isAlive: Bool { get set }
var isDead: Bool { get set }
init(isAlive: Bool)
init(isDead: Bool)
init()
}
That would be more like a functional port. It does not seem to take care of the fact that Variant records are actually meant to use the same piece of memory in different ways, so if you'd have some low-level code that reads from a stream or you have a pointer to such a structure, this might not help you.
In that case you might want to try just reserving some bytes, and write different getters/setters to access them. That would even work if you'd have to port more complex structures, like nested variant types.
But overall, if possible, I'd recommend to avoid porting such structures too literally, and use idioms that match Swift better.
I'm trying to write a "Restriction" of some data type, where a Restriction could be a list of Interest(enum), Experience(a range of years) or isVerified(boolean), etc. I have another class that has a property [Restriction]?.
I'm thinking about using enum but I'm not sure what's the correct/better way to construct this enum? Or maybe use struct? Any suggestions?
It's not clear from you question what "Restriction" means to you, but the way to decide is to say out loud what it means, and then use grammar to pick your types.
A struct is an "AND" type. For example:
struct Point {
let x: Double
let y: Double
}
A Point has an x coordinate AND a y coordinate. If a restriction has an interest and an experience level and a verification status, then that's a struct.
An enum is an "OR" type. For example:
enum Color {
case red
case blue
case green
}
A Color is red OR blue OR green. An enum case may also have associated data. For example:
enum Pattern {
case solid(Color)
case striped(Color, Color)
}
A Pattern is either solid with a single color OR it is striped with two colors. Notice the grammar again that helps us recognize our type: "x with y OR a with b."
Structs, classes, and tuples are all AND types, so you need some more rules to split them up. Tuples are basically anonymous structs, and they are mostly useful in Swift for short-lived, temporary values, like return values. If you find yourself wanting to create a typealias for a tuple, you probably wanted a struct instead. I find people overuse tuples (in Swift; they make more sense in other languages).
Structs are value types, while classes are reference types. The best way to understand the difference is that a value type is only its value. Any "instance" of the number 4 is identical to any other instance of the number 4. Nothing "owns" the number 4. You don't care where the number 4 came from. That's a value. The same is true for a Point. The Point (1,2) is entirely defined by the number 1 followed by the number 2. There is nothing else you can say about that Point. If your type is entirely defined by its properties, that is a good case for a struct. It should be easy to define equality between two values.
Classes are reference types. Reference types have identity. Two instances may have all the same property values, but be different "objects." When you want to ask "which one is this?" then you mean a class, not a struct. If you want to make sure two variables are "the same object" (rather than just "equal"), then you mean a class. There is a lot of pressure in Swift to use structs, but in practice, classes are extremely common, particularly in iOS development.
Thinking about what your type means, and saying it with clear language, will help you find the right types for your problem. If you're interested in a longer version of this, see Learning From Our Elders.
EDIT: Looking at your edits, I think what you're really building is a predicate. A predicate is just a function that returns yes or no given some value, and that's what I think a Restriction probably is. It looks like you want a collection of restrictions. I assume you want to then AND them all together.
A very nice way to build a predicate is with a closure. For example:
struct Element {
let interests: [String]
let experience: Int
}
struct Restriction {
let passes: (Element) -> Bool
init(hasInterest interest: String) {
passes = { $0.interests.contains(interest) }
}
init(hasAtLeastExperience years: Int) {
passes = { $0.experience >= years }
}
}
let element = Element(interests: ["fishing", "sewing"], experience: 5)
let restriction = Restriction(hasAtLeastExperience: 2)
restriction.passes(element)
With this you can easily build up groups of restrictions, apply them with AND or OR, etc.
Go with the Struct in your case because Structs are preferable if they are relatively small and copiable because copying is way safer than having multiple reference to the same instance as happens with classes. Your interest can be a list of the enum type Interest.
enum Interest {
}
struct Restriction {
let interest: [Interest]
let experience: Int
let isVerified: Bool
}
In a Swift app I have a function that only accepts integers between +2 and positive infinity. Is there any way to enforce this at compile time?
Updated with a small code sample:
To calculate a Fibonacci sequence we need at least two numbers to start with, anything else is an error. Here I use guard and an failable initializer to verify this at runtime.
struct FibonacciSeed {
var magnitude = 2
init() { }
init?( magnitude: Int ) {
guard magnitude > 1 else { return nil }
self.magnitude = magnitude
}
var seed: [Int] {
// return valid seed ...
}
}
I was curious if there were some fancy way to enlist the help of the compiler to enforce this at compile time. Like the compiler doesn't let me compile:
var a:UInt = -8
There is no such feature in Swift. Compiler cannot know at compile time what kind of values the application passes to functions at runtime. As a runtime feature it would just make the Swift runtime libraries bigger. That would make applications bigger even if they don't use the specific feature. I'm quite sure Apple want to keep the libraries as small as possible.
For Friday Fun, I wanted to model Angles in interchangable formats. I'm not sure if I've done it in the most Swift idiomatic way, but I'm learning. So I have an Angle protocol, and then 3 different struct types (Radians, Degrees, and Rotations) which all conform to the Angle protocol. I'd like to be able to add/subtract them, but the trick is, I want the lhs argument to dictate the return type. For example:
Degrees(180) + Rotations(0.25) --> Degrees(270)
or
Rotations(0.25) + Radians(M_PI) -> Rotations(0.75)
What I was hoping was I could do something like
func + (lhs:Angle, rhs:Angle) -> Angle {
return lhs.dynamicType(rawRadians: lhs.rawRadians + rhs.rawRadians)
}
The Angle protocol requires a var rawRadians:CGFloat { get } as well as an init(rawRadians:CGFloat)
I could do this with a Smalltalk-esque double dispatch approach, but I think there most be a more Swift appropriate approach (especially one that requires less code, double dispatch requires a lot of boilerplate code).
You just need a generic addition:
func +<A: Angle>(lhs: A, rhs: Angle) -> A {
return A(rawRadians: lhs.rawRadians + rhs.rawRadians)
}
This way the addition will return whatever type is on the lhs.
Generally speaking, if you're using dynamicType, you're probably fighting Swift. Swift relies more on generics and protocols (i.e. static type information at compile time) rather than dynamic dispatch (i.e dynamic type information at runtime).
In this code, as you say, A is a placeholder for "some type, that conforms to Angle, to be determined at compile time." So in your first example:
Degrees(180) + Rotations(0.25) --> Degrees(270)
This actually calls a specialized function +<Degrees>. And this:
Rotations(0.25) + Radians(M_PI) -> Rotations(0.75)
calls a (logically) different function called +<Rotations>. The compiler may choose to optimize these functions into a single function, but logically they are independent functions, created at compile time. It's basically a shortcut for writing addDegrees(Degrees, Angle) and addRotations(Rotations, Angle) by hand.
Now, to your question about a function that takes two Angles and returns.... well, what? If you want to return an Angle in this case, that's easy, and exactly matches your original signature:
func +(lhs: Angle, rhs: Angle) -> Angle {
return Radians(rawRadians: lhs.rawRadians + rhs.rawRadians)
}
"But..." you're saying, "that returns Radians." No it doesn't. It returns Angle. You can do anything "angle-like" on it you want. The implementation details are opaque as they should be. If you care that the underlying data structure is a Radians, you're almost certainly doing something wrong.
OK, there is one side case where it may be useful to know this, and that's if you're printing things out based on how you go them. So if the user gave you degree information to start, then you want to print everything in degrees (using a description method that you didn't mention). And maybe that's worth doing in that particular case.If you want to, your original code was very close:
func +(lhs: Angle, rhs: Angle) -> Angle {
return lhs.dynamicType.init(rawRadians: lhs.rawRadians + rhs.rawRadians)
}
But it's critical to understand that this doesn't match your request to have "the lhs argument to dictate the return type." This causes the lhs argument to dictate the return implementation. The return type is always Angle. If you want to change the return type, you need to use the generics.
I was wondering: What is the best way to declare a non-ordered list of scalar values in Swift, that are fully backed by a symbol and are liable to be checked by the compiler?
Let's say I want to declare a list of LetterSpacing values that I want to access and use in my code via their symbols.
My understanding is that I should declare an swift enum like this:
enum LetterSpacing: Double {
case Short = 1.0
case Medium = 2.0
case Large = 3.0
}
This works fine and gets compiler checks but the annoying part is that I need to LetterSpacing.XXX.rawValue each time to access the underlying value. The .rawValue bothers me a bit to have to specify this everywhere.
I suppose it wouldn't make sense or would be inappropriate to declare a struct with three static let Short = 1.0 etc..
So, how would you handle such cases? Is it possible to add somekind of protocol/extension swift magic to the existing types to be able to have the Short enum act as its own value? (i.e. let size = LetterSpacing.Short would be of type Double and have a value of 1.0)
The enum would be preferred for multiple reasons.
First, the enum actually ends up with a smaller memory footprint. This is because Swift optimizing enum values into a single byte (no matter what the raw value is), and we only get the full value out of it when we call rawValue on the enum value. Paste the following code into a playground to see:
struct LetterSpacingS {
static let Short: Double = 1.0
}
enum LetterSpacingE: Double {
case Short = 1.0
}
sizeofValue(LetterSpacingS.Short)
sizeofValue(LetterSpacingE.Short)
The double is 8 bytes, while the enum is just 1.
Second, the importance of the first point extends beyond just memory footprint. It can apply to the execution efficiency of our program as well. If we want to compare two values from our struct, we're comparing 8 bytes. If we want to compare two of our enum values, we comparing just a single byte. We have 1/8th as many bytes to compare in this specific case. And this is just with a double. Consider that Swift enums can also have a string as a backing type. Comparing two strings can be extraordinarily expensive versus just comparing the single byte they're hidden behind in an enum.
Third, using the enum, we're not comparing floating point numbers, which you really don't want to do, generally speaking.
Fourth, using the enum gives us some type safety that we can't get with the struct of constants. All the struct of constants does is let us define a handful of predefined constants to use.
struct LetterSpacingS {
static let Short = 1.0
static let Medium = 2.0
static let Long = 3.0
}
But now what would a method look like that expects one of these values?
func setLetterSpacing(spacing: Double) {
// do stuff
}
And now what happens when Joe-Coder comes in and does:
foo.setLetterSpacing(-27.861)
Nothing's stopping him. It takes a double, any double. This might not be so common, but if this is in a library you're distributing, you are leaving yourself open to questions and comments like "When I pass a value of 5.0 in, it doesn't look right at all!"
But compare this to using the enum.
func setLetterSpacing(spacing: LetterSpacing) {
// do stuff
}
And now, we only get the three predefined choices for what to pass into this argument.
And outside of your internal use for the values held by the enum, you should have to use rawValue too much.
The fifth reason isn't a strong reason for using an enum over a struct, but mostly just a point to make to eliminate one of the reasons suggested for using a struct over an enum. Swift enums can be nested in other types, and other types can be nested in Swift enums. You don't have to use a struct to get nested types.
I don't see why creating a Struct with three static constants would be inappropriate. I see a lot of Swift code (also from Apple) that does this.
Structs lets you create nice hierarchies:
struct Style {
struct Colors {
static let backgroundColor = UIColor.blackColor()
...
}
struct LetterSpacing {
static let Short = 1.0
}
...
}