Swift: Properly initialize SIMD3 and call it from struct - ios

I am trying call the defined struct so I am able to change its value when a button is pressed. I am having trouble with calling SIMD3 inside a struct. Currently I have,
struct CaptureData {
var vertices: [SIMD3<Float>]
var mode: Mode = .one
mutating func nextCase() {
mode = mode.next()
}
var verticesFormatted : String {
let v = "<" + vertices.map{ "\($0.x):\($0.y):\($0.z)" }.joined(separator: "~") + "method: \(mode.next().rawValue)"
return "\(v)"
}
}
And the extension that I got helped earlier from #Joshua
enum Mode: String, CaseIterable {
case one, two, three
}
extension CaseIterable where Self: Equatable {
var allCases: AllCases { Self.allCases }
var nextCase: Self {
let index = allCases.index(after: allCases.firstIndex(of: self)!)
guard index != allCases.endIndex else { return allCases.first! }
return allCases[index]
}
#discardableResult
func next() -> Self {
return self.nextCase
}
}
I am trying to initialize var instance = CaptureData(vertices: [SIMD3<Float>]), but the error comes: Cannot convert value of type '[SIMD3<Float>].Type' to expected argument type '[SIMD3<Float>]'
#Jousha also suggested me to use the following:
typealias XYZVar = (x: Float, y: Float, z: Float)
struct CaptureData {
var vertices:[XYZVar]
.... other variables
}
However, I also tried that with var instance = CaptureData(vertices: [XYZVar]) and it also not working: Cannot convert value of type '[XYZVar].Type' (aka 'Array<(x: Float, y: Float, z: Float)>.Type') to expected argument type '[XYZVar]' (aka 'Array<(x: Float, y: Float, z: Float)>')
My question is, how to I call SIMD3 properly and fix the above error from var instance = CaptureData(vertices: [SIMD3<Float>])?
Thanks so much in advance.

Hmm, where do I start here?
You are passing [SIMD3<Float>] and [XYZVar] which are types, to a function/initializer that expects a value as a parameter. That's why the compiler is complaining.
Let me explain.
In swift when you write var vertices: [SIMD3<Float>] you are saying: "vertices" is an array of SIMD3<Float>. Now, if you want to assign a value to "vertices" you can do so by writing vertices = [] or vertices = [SIMD3<Float>]() they are equivalent.
I did some changes to your code. Take a look:
import simd
enum Mode: String, CaseIterable {
case one, two, three
}
extension CaseIterable where Self: Equatable {
var allCases: AllCases { Self.allCases }
var nextCase: Self {
let index = allCases.index(after: allCases.firstIndex(of: self)!)
guard index != allCases.endIndex else { return allCases.first! }
return allCases[index]
}
#discardableResult
func next() -> Self {
return self.nextCase
}
}
struct CaptureData {
var vertices: [SIMD3<Float>]
var mode: Mode = .one
mutating func nextCase() {
mode = mode.next()
}
var verticesFormatted : String {
let verticesDescribed = vertices
.map({ "\($0.x):\($0.y):\($0.z)" })
.joined(separator: "~")
let v = "< \(verticesDescribed) method: \(mode.next().rawValue)"
return v
}
}
let data = CaptureData(vertices: [
SIMD3<Float>(x: 0, y: 0, z: 0),
SIMD3<Float>(x: 0.5, y: 1, z: 0),
SIMD3<Float>(x: 1, y: 0, z: 0)
])
print(data.verticesFormatted)
// prints: < 0.0:0.0:0.0~0.5:1.0:0.0~1.0:0.0:0.0 method: two

Related

Generic class of generic class with one argument/parameter

I have this syntactical issue with my data structure. What makes it worse is that I can not talk about it in detail. The company I am employed at operates in the public transportation sector and I am under NDA and boss would kill me if I posted anything too specific. I hope you understand!
I have this perfect example though. There are no inconsistencies at all ;)
Well, okay, there are. However I am convinced that most of you out there are smart enough to get what is of importance here.
Basic structure:
class Propulsion {
var horsePower: Double
init(horsePower: Double) {
self.horsePower = horsePower
}
static let pedes = Propulsion(horsePower: 0.2)
}
class Motor: Propulsion {
var range: Double
init(range: Double, horsePower: Double) {
self.range = range
super.init(horsePower: horsePower)
}
static let otto = Motor(range: 1000, horsePower: 100)
static let electric = Motor(range: 400, horsePower: 200)
}
class Vehicle<P: Propulsion> {
var propulsion: P
init(propulsion: P) {
self.propulsion = propulsion
}
}
class Bicycle<P: Propulsion>: Vehicle<P> {
var hasFrontSuspension: Bool
init(hasFrontSuspension: Bool, propulsion: P) {
self.hasFrontSuspension = hasFrontSuspension
super.init(propulsion: propulsion)
}
}
class Car<P: Propulsion>: Vehicle<P> {
func rangePerHorsePower() -> Double where P: Motor {
propulsion.range / propulsion.horsePower
}
}
Now I would like to declare a parking spot for a car. Like so:
var carParkingSpot: ParkingSpot<Car<Motor>>
For the class ParkingSpot I have some class like this in mind:
class ParkingSpot<V: Vehicle<P>> where P: Propulsion {
var vehicle: Vehicle<P>
init(vehicle: Vehicle<P>) {
self.vehicle = vehicle
}
func taxForRange() -> Double where P: Motor {
vehicle.propulsion.range * 50
}
}
From the last bit I get back a bunch of
Cannot find type 'P' in scope
This one doesn’t work either:
class ParkingSpot<V: Vehicle<P: Propulsion>>
Expected '>' to complete generic argument list
This implementation works though:
class ParkingSpot<V: Vehicle<P>, P: Propulsion> {
var vehicle: Vehicle<P>
init(vehicle: Vehicle<P>) {
self.vehicle = vehicle
}
func taxForRange() -> Double where P: Motor {
vehicle.propulsion.range * 50
}
}
However I don’t want to duplicate the Motor bit:
var carParkingSpot: ParkingSpot<Car<Motor>, Motor>
How can I accomplish this with just one generic parameter?
You may use the "Protocol oriented" approach:
protocol PropulsionP {
var horsePower: Double { get }
}
protocol MotorP: PropulsionP {
var range: Double { get }
}
struct MotorS: MotorP {
var range: Double
var horsePower: Double
init(range: Double, horsePower: Double) {
self.range = range
self.horsePower = horsePower
}
}
protocol VehicleP {
associatedtype P: PropulsionP
var propulsion: P { get }
}
struct BicycleS<Prop: PropulsionP>: VehicleP {
let hasFrontSuspension: Bool
var propulsion: Prop
init(
hasFrontSuspension: Bool,
propulsion: Prop
) {
self.hasFrontSuspension = hasFrontSuspension
self.propulsion = propulsion
}
}
struct CarS<Prop: PropulsionP>: VehicleP {
var propulsion: Prop
func rangePerHorsePower() -> Double where P: MotorP {
propulsion.range / propulsion.horsePower
}
}
struct ParkingSpotS<V: VehicleP> {
var vehicle: V
init(vehicle: V) {
self.vehicle = vehicle
}
func taxForRange() -> Double where V.P: MotorP {
vehicle.propulsion.range * 50
}
}
var carParkingSpot: ParkingSpotS<CarS<MotorS>>
No double MotorS bit.
Quod erat demonstrandum.
I used the somewhat unusual naming to emphasize the point.
(needed to make some edit, erronously typed Motor where I actually need MotorP)
Update
I was on the road with my preferred car and tried it out:
var carParkingSpot: ParkingSpotS<CarS<MotorS>> = .init(
vehicle: .init(
propulsion: .init(
range: 760,
horsePower: 240
)
)
)
print(carParkingSpot.taxForRange())
38000.0
Alternatively you can use this initialiser:
var carParkingSpot: ParkingSpotS = .init(
vehicle: CarS(
propulsion: MotorS(
range: 760,
horsePower: 240
)
)
)
Update
Now suppose you are utilising a third party library which already provides a nice implementation of a motor.
What you need to do is to implement an extension for their given class or struct TheirMotor which conforms to your protocol MotorP:
import FancyMotors
extension TheirMotor: MotorP {
let range: Double {
// calculate `range` in terms of the
// given API of `TheirMotor`:
...
return range
}
}
Then, you can use it like below:
var carParkingSpot: ParkingSpotS = .init(
vehicle: CarS(
propulsion: TheirMotor(
distance: 760,
power: 240
)
)
)
Note, that you use TheirMotor and need to use the appropriate initialiser to create it.
This seems to work:
class ParkingSpot<V: Vehicle<Propulsion>>
{
var vehicle: V
init(vehicle: V)
{
self.vehicle = vehicle
}
func taxForEngineeNoise() -> Double
{
switch vehicle.propulsion
{
case is Motor:
return vehicle.propulsion.horsePower * 50
default:
...
}
}
func taxForRange() -> Double
{
if let motor = vehicle.propulsion as? Motor
{
return motor.range * 50
}
else
{
...
}
}
}
Alternatively, perhaps hide the duplication where you can?
typealias ParkingSpotX = ParkingSpot<Car<Motor>, Motor>
var parkingSpot: ParkingSpotX

How To constraint parameter of generic type in function, to sibling parameter

To understand the origin of the question, let's start with some code:
protocol MyProtocol {
var val1: Int { get set }
}
struct StructA: MyProtocol {
var val1: Int
var structAVal: Int
}
struct StructB: MyProtocol {
var val1: Int
var structBVal: Int
var thirdProperty: Int
}
And then I have a struct with a heterogeneous array of type MyProtocol:
struct Values {
var arr: [MyProtocol] = [StructA(val1: 0, structAVal: 0), StructB(val1: 0, structBVal: 0)]
}
if I was to change one of the values with a method in Values such as:
struct Values {
var arr: [MyProtocol] = [StructA(val1: 0, structAVal: 0), StructB(val1: 0, structBVal: 0)]
mutating func set<T: MyProtocol>(at index: Int, _ newValue: T) {
arr[index] = newValue
}
}
That would be smooth.
The problem which I am facing is, say I wanted to change var thirdProperty: Int in the structB item in var arr: [MyProtocol], I would not be able to do so which my mutating func set<T: MyProtocol>(at index: Int, _ newValue: T), since It only knows of MyProtocol types.
So my 2 cents to resolve this matter was using a closure something like this:
mutating func set<T: MyProtocol>(at index: Int, closure: (T?) -> (T)) {
arr[index] = closure(arr[index] as? T)
}
The problem with this is that every time I invoke this method, I would first need to downcast the parameter (from MyProtocol to StructB). which seems more of a workaround which could invite unwanted behaviours along the road.
So I started thinking maybe there is a way to constraint the generic parameter to a sibling parameter something like this (pseudo code):
mutating func set<T: MyProtocol>(type: MyProtocol.Type, at index: Int, closure: (T?) -> (T)) where T == type {
arr[index] = closure(arr[index] as? T)
}
Which as you guessed, does not compile.
Any thought on how to approach this matter in a better manner. T.I.A
Use T.Type instead of MyProtocol.Type in the set(type:at:closure:) method.
struct Values {
var arr: [MyProtocol] = [StructA(val1: 0, structAVal: 0), StructB(val1: 0, structBVal: 0, thirdProperty: 0)]
mutating func set<T: MyProtocol>(type: T.Type, at index: Int, closure: ((T?) -> (T?))) {
if let value = closure(arr[index] as? T) {
arr[index] = value
}
}
}
Example:
var v = Values()
v.set(type: StructB.self, at: 1) {
var value = $0
value?.thirdProperty = 20
return value
}
Do let me know if this is the right understanding of your requirement.
PGDev's solution gets to the heart of the question, but IMO the following is a bit easier to use:
enum Error: Swift.Error { case unexpectedType }
mutating func set<T: MyProtocol>(type: T.Type = T.self, at index: Int,
applying: ((inout T) throws -> Void)) throws {
guard var value = arr[index] as? T else { throw Error.unexpectedType }
try applying(&value)
arr[index] = value
}
...
var v = Values()
try v.set(type: StructB.self, at: 1) {
$0.thirdProperty = 20
}
The = T.self syntax allows this to be simplified a little when the type is known:
func updateThirdProperty(v: inout StructB) {
v.thirdProperty = 20
}
try v.set(at: 1, applying: updateThirdProperty)
Another approach that is more flexible, but slightly harder on the caller, would be a closure that returns MyProtocol, so the updating function can modify the type. I'd only add this if it were actually useful in your program:
mutating func set<T: MyProtocol>(type: T.Type = T.self, at index: Int,
applying: ((T) throws -> MyProtocol)) throws {
guard let value = arr[index] as? T else { throw Error.unexpectedType }
arr[index] = try applying(value)
}
...
try v.set(type: StructB.self, at: 1) {
var value = $0
value.thirdProperty = 20
return value // This could return a StructA, or any other MyProtocol
}
(Which is very close to PGDev's example, but doesn't require Optionals.)

Swift iOS -Compare elements in 1 array by property

I have an array of objects and I want to compare the objects based on property to find out if the properties are all the same. Right now I loop through all the objects, place all values of the properties in a separate array, and then use filterArr.allSatisfy { $0 == filterArr.last } to detemermine wether the properties are all the same or not.
This method works but I know there has to be a more elegant way then what I'm doing.
I actually went looking for an answer to this but every single thing I came across was comparing the elements of 2 different arrays instead of 1.
class IceCream {
var flavor: String?
var price: Double?
}
let iceCream1 = IceCream()
iceCream1.flavor = "vanilla"
iceCream1.price = 1.5
let iceCream2 = IceCream()
iceCream2.flavor = "chocolate"
iceCream2.price = 2.0
let iceCream3 = IceCream()
iceCream3.flavor = "vanilla"
iceCream3.price = 1.5
let iceCream4 = IceCream()
iceCream4.flavor = "strawberry"
iceCream4.price = 2.5
let iceCreams = [iceCream1, iceCream2, iceCream3, iceCream4]
var filterArr = [String]()
for iceCream in iceCreams {
filterArr.append(iceCream.flavor ?? "")
}
let areItemsEqual = filterArr.allSatisfy { $0 == filterArr.last }
print(areItemsEqual) // prints false
You can avoid having to initialize and then assign the properties on separate lines with a struct.
struct IceCream {
let flavor: String?
let price: Double?
}
let iceCreams: [IceCream] = [
IceCream(flavor: "vanilla", price: 1.5),
IceCream(flavor: "chocolate", price: 2.0),
IceCream(flavor: "vanilla", price: 1.5),
IceCream(flavor: "strawberry", price: 2.5)
]
Using the generics sugar provided by #Alexander and #matt, we have a nice looking extension.
extension Collection {
func allEqual<T: Equatable>(by key: KeyPath<Element, T>) -> Bool {
return allSatisfy { first?[keyPath:key] == $0[keyPath:key] }
}
}
print(iceCreams.allEqual(by: \.flavor))
Alternatively, you could specify an IceCream be equal to one another by flavor.
extension IceCream: Equatable {
static func == (lhs: IceCream, rhs: IceCream) -> Bool {
return lhs.flavor == rhs.flavor
}
}
extension Collection where Element: Equatable {
func allEqual() -> Bool {
return allSatisfy { first == $0 }
}
}
print(iceCreams.allEqual())
Here's a pretty Swifty way to do it. I define an extension on Collection that checks for equality among the collection's items, according to a given predicate:
extension Collection {
func allEqual<T: Equatable>(by deriveKey: (Element) -> T) -> Bool {
guard let firstElement = self.first else {
return true // empty lists are all-equal
}
let sampleKey = deriveKey(firstElement)
return self.dropFirst().allSatisfy{ deriveKey($0) == sampleKey }
}
}
struct IceCream {
let flavor: String
let price: Double
}
let iceCreams = [
IceCream(flavor: "vanilla", price: 1.5),
IceCream(flavor: "chocolate", price: 2.0),
IceCream(flavor: "vanilla", price: 1.5),
IceCream(flavor: "strawberry", price: 2.5)
]
let allItemsEqualByFlavour = iceCreams.allEqual(by: { $0.flavor})
print(allItemsEqualByFlavour) // false
let vanillaOnlyIceCreams = iceCreams.filter{ $0.flavor == "vanilla" }
print(vanillaOnlyIceCreams.allEqual(by: { $0.flavor})) // true
Here's an elegant way to make sure your ice creams are the same along any arbitrary axis, i.e. either flavor or price or any other equatable property you may later inject:
extension Array {
func allSameForProperty<T:Equatable> (_ p:KeyPath<Element,T>) -> Bool {
return self.isEmpty || self.allSatisfy{
self.first![keyPath:p] == $0[keyPath:p]
}
}
}
Let's test it. First, some initial conditions:
struct Icecream {
let flavor : String
let price : Double
}
let arr = [
Icecream(flavor: "vanilla", price: 1.5),
Icecream(flavor: "vanilla", price: 1.75)
]
And now the actual test:
arr.allSameForProperty(\Icecream.flavor) // true
arr.allSameForProperty(\Icecream.price) // false

How to make a generic Vertex so that I can create Graphs (Collections) with mixed types?

I am having trouble with a design of a Vertex struct. I want to be able to create "Array" or "Set" so my "Vertex" doesnt all have to be the same type. Both situations are giving different errors. Check code below.
Thank you in advance
import Foundation
public struct Vertex<T: Equatable> where T: Equatable, T: Hashable {
public var data: T
public let index: Int?
init(data: T , index: Int ) {
self.data = data
self.index = index
}
}
extension Vertex: CustomStringConvertible {
public var description: String {
return "\(index): \(data)"
}
}
struct Coordinate {
var x : Int
var y : Int
init(x : Int, y: Int) {
self.x = x
self.y = y
}
}
extension Coordinate: Equatable {}
func ==(lhs: Coordinate, rhs: Coordinate) -> Bool {
guard lhs.x == rhs.x else {
return false
}
guard lhs.y == rhs.y else {
return false
}
return true
}
extension Coordinate: Hashable {
var hashValue: Int {
return "\(x)\(y)".hashValue
}
}
let coord1 = Coordinate(x : 5, y: 5)
let stringVertex1 = Vertex(data: "Hello World", index: 3)
let stringVertex2 = Vertex(data: "Foo ", index: 3)
let intVertex1 = Vertex(data: 2, index: 1)
let coordVertex1 = Vertex(data: coord1, index: 1)
//Error: Cannot convert value of type 'Vertex<String>' to expected element type 'Vertex'.
//Even if I make myArr1 equal to [stringVertex1, stringVertex1], I still get the same error.
let myArr1 : Array<Vertex> = [stringVertex1, intVertex1]
//This works since the data inside "Vertex" is the same type.
let myArr2 : Array<Vertex<String>> = [stringVertex1, stringVertex2]
//Error: Type "Vertex" does not conform to protocol "Hashable".
let mySet1 : Set<Vertex> = [stringVertex1, stringVertex2]
I got my answer. This is the final vertex code. THE POWER OF POP!
public enum TypeOfVertex : String {
case Int = "Mirror for Int"
case Float = "Mirror for Float"
case Double = "Mirror for Double"
case Coordinates = "Mirror for Coordinate"
case String = "Mirror for String"
}
protocol AnyVertexable {
var type: TypeOfVertex { get set }
var index: Int { get set }
}
struct Vertex<Element : Hashable> : AnyVertexable where Element: Equatable & Hashable {
var type : TypeOfVertex
var index: Int
var data : Element?
init(index: Int, data: Element) {
self.data = data
self.index = index
if let type = TypeOfVertex(rawValue: data.hashValue.customMirror.description) {
self.type = type
} else {
fatalError()
}
}
}
let sample1 = Vertex(index: 0, data: 1.0)
let sample2 = Vertex(index: 2, data: 1)
let sample3 = Vertex(index: 3, data: Coordinate(x: 5, y: 5))
let myArr : [AnyVertexable] = [sample1, sample2, sample3]

Using filter on Objects in an Array to find max? [swift]

I have a bunch of Objects stored in an Array.
They all have the property:
distanceInSeconds: Int
I was wondering if there's a way to find the max of this property between all objects in the array using filter or another array method?
For instance:
var distances: [Distance] = []
var maxDistance = distances.filter(find max)
This would be the Swifty way (by implementing Comparable):
class Route : Comparable {
let distance: Int
init(distance: Int) {
self.distance = distance
}
}
func ==(lhs: Route, rhs: Route) -> Bool {
return lhs.distance == rhs.distance
}
func <(lhs: Route, rhs: Route) -> Bool {
return lhs.distance < rhs.distance
}
let routes = [
Route(distance: 4),
Route(distance: 8),
Route(distance: 2),
Route(distance: 7)
]
print(routes.maxElement()?.distance)
output:
"8"
This works with Swift 2. If you're using Swift 1.2, maxElement(routes) should work
In Swift 2.0 minElement and maxElement now return optionals in case of empty sequences, and also now have versions that take isOrderedBefore closures.
let maxDistance = distances.maxElement { (a, b) -> Bool in
a.distanceInSeconds < b.distanceInSeconds
}
#1. The element type inside your sequence conforms to Comparable protocol
With Swift 4, if the element type inside your sequence conforms to Comparable protocol, you will be able to use the max() method that has the following declaration:
func max() -> Self.Element?
Returns the maximum element in the sequence.
Usage:
class Distance: Comparable, CustomStringConvertible {
let distanceInSeconds: Int
var description: String { return "Distance in Int: \(distanceInSeconds)" }
init(distanceInSeconds: Int) {
self.distanceInSeconds = distanceInSeconds
}
static func ==(lhs: Distance, rhs: Distance) -> Bool {
return lhs.distanceInSeconds == rhs.distanceInSeconds
}
static func <(lhs: Distance, rhs: Distance) -> Bool {
return lhs.distanceInSeconds < rhs.distanceInSeconds
}
}
let distances = [
Distance(distanceInSeconds: 20),
Distance(distanceInSeconds: 30),
Distance(distanceInSeconds: 10)
]
let maxDistance = distances.max()
print(String(describing: maxDistance)) // prints: Optional(Distance in Int: 30)
#2. The element type inside your sequence does not conform to Comparable protocol
With Swift 4, if the element type inside your sequence does not conform to Comparable protocol, you will have to use the max(by:) method that has the following declaration:
func max(by areInIncreasingOrder: ((offset: Int, element: Base.Element), (offset: Int, element: Base.Element)) throws -> Bool) rethrows -> (offset: Int, element: Base.Element)?
Returns the maximum element in the sequence, using the given predicate as the comparison between elements.
Usage:
class Distance: CustomStringConvertible {
let distanceInSeconds: Int
var description: String { return "Distance in Int: \(distanceInSeconds)" }
init(distanceInSeconds: Int) {
self.distanceInSeconds = distanceInSeconds
}
}
let distances = [
Distance(distanceInSeconds: 20),
Distance(distanceInSeconds: 30),
Distance(distanceInSeconds: 10)
]
let maxDistance = distances.max (by: { (a, b) -> Bool in
return a.distanceInSeconds < b.distanceInSeconds
})
print(String(describing: maxDistance)) // prints: Optional(Distance in Int: 30)
I think you want reduce:
Setup:
struct Distance {
var distanceInSeconds: Int
}
var distances: [Distance] = []
for _ in 1...10 {
distances += [Distance(distanceInSeconds: Int(arc4random_uniform(100)))]
}
Implementation:
let max = distances.reduce(distances.first) {
if let left = $0 where left.distanceInSeconds > $1.distanceInSeconds {
return $0
} else {
return $1
}
}

Resources