I have a protocol "Visual" which is implemented by two classes : Point2D and Square
protocol Visual {
var text: String { get }
}
class Point2D : Visual {
var text: String
var x: Double
var y: Double
init(x : Double , y : Double)
{
self.x = x
self.y = y
self.text = "I'm 2d point"
}
}
class Square : Visual {
var text: String
var x: Int
init(x : Int)
{
self.x = x
self.text = "I'm square"
}
}
I have made a class Storage which will keep in array the elements and has two operations add and delete
class Storage
{
var elements : [Visual]
init()
{
elements = [Visual]()
}
func add(item : Visual)
{
elements.append(item)
}
func delete(item : Visual)
{
}
func printItems()
{
print(elements)
}
}
The add works fine , but how should I implement the delete since I pass object with refrence to "Visual".I want to delete the first seen object from left to right ?
First of all, you need a way to evaluate the equality of them. I would suggest something like this. (I found this answer about equality on protocol very helpful.)
protocol Visual {
var text: String { get }
func isEqual(to other: Visual) -> Bool
}
extension Point2D {
func isEqual(to other: Visual) -> Bool {
return (other as? Self).flatMap({ $0.x == self.x && $0.y == self.y }) ?? false
}
}
extension Square {
func isEqual(to other: Visual) -> Bool {
return (other as? Self).flatMap({ $0.x == self.x }) ?? false
}
}
You can then find the first index of the item you want to delete and remove it using the returned index.
class Storage {
// ...
func delete(item : Visual) {
if let index = elements.firstIndex(where: { $0.isEqual(to: item) }) {
elements.remove(at: index)
}
}
}
You can implement the Equatable protocol when you declare Visual protocol, in this way you will be enable to compare object and to understand which are equals and they have to be removed.
Related
Ahoy everyone,
I have recently been trying to implement a Node based graph system that passes data between nodes using plugs. Similar to many of the 3D applications like houdini and maya.
I have written a similar system before using Python, and wanted to try this with Swift as my first learning excersise. Boy did I jump into the deep end on this one.
I am stuck now with Swifts Arrays, as I would like to store a list of Generic plugs.
Each plug can have its own value type float, int, color, string, Vector Matrix.
I have read up about Type Erasers and opaque types, but still cant seem to get my values our of a list in a way that I can perform some arithmetic on them.
All and any help that might put me in the direction would be greatly appreciated :D
import Foundation
import MetalKit
protocol genericPlug {
associatedtype T
func GetValue() -> T
}
class Plug<T>:genericPlug{
var _value:T?
var value:T {
get{GetValue()}
set(val){
value = val
}
}
func GetValue() -> T{
return _value!
}
init(_ newValue:T){
_value=newValue
}
}
class Node{
var plugs:[genericPlug] = []
init(){
var p1 = Plug<Int>(0)
var p2 = Plug(vector2(1.2, 3.1))
var p3 = Plug([0.0, 3.1, 0.6, 1])
plugs.append(p1)
plugs.append(p2)
plugs.append(p3)
}
func execute(){
// will access the plugs in the array and perform some sort of calculations on them.
plugs[0].value + 1 // should equal 1
plugs[1].value.x + 0.8 // should have x=2.0 y=3.1
plugs[2].value[1] - 0.1 // should equal 3.0
}
}
Thanks everyone
Use a generic something to extract what you need. Your options are methods and subscripts.
protocol PlugValue {
init()
}
extension Int: PlugValue { }
extension Float: PlugValue { }
extension Double: PlugValue { }
extension SIMD3: PlugValue where Scalar == Int32 { }
struct Plug<Value: PlugValue> {
var value: Value
init(_ value: Value) {
self.value = value
}
}
protocol AnyPlug {
var anyValue: PlugValue { get }
}
extension AnyPlug {
subscript<Value: PlugValue>(type: Value.Type = Value.self) -> Value {
anyValue as? Value ?? .init()
}
func callAsFunction<Value: PlugValue>(_ type: Value.Type = Value.self) -> Value {
anyValue as? Value ?? .init()
}
}
extension Plug: AnyPlug {
var anyValue: PlugValue { value }
}
let plugs: [AnyPlug] = [
Plug(1),
Plug(2.3 as Float),
Plug(4.5),
Plug([6, 7, 8] as SIMD3)
]
plugs[0][Int.self] // 1
plugs[1][Double.self] // 0
plugs[1][] as Float // 2.3
let double: Double = plugs[2]() // 4.5
plugs[3](SIMD3.self).y // 7
With the array of protocols, do you have to down cast them into their Plug when retrieving them every time?
Essentially. This is true of all heterogenous sequences. Here are your options:
extension Array: PlugValue where Element: PlugValue { }
let plug: AnyPlug = Plug([0.1, 1.1, 2.1])
(plug as? Plug<[Double]>)?.value[1]
(plug.anyValue as? [Double])?[1]
extension Plug {
enum Error: Swift.Error {
case typeMismatch
}
}
extension AnyPlug {
func callAsFunction<Value: PlugValue, Return>(_ closure: (Value) -> Return) throws {
guard let value = anyValue as? Value
else { throw Plug<Value>.Error.typeMismatch }
closure(value)
}
}
try plug { (doubles: [Double]) in doubles[1] } // 1.1
try plug { ($0 as [Double])[1] } // 1.1
try plug { $0 as Int } // <Swift.Int>.Error.typeMismatch
I managed to find a solution that worked for my needs.
I am still looking at finding a better way to handle getting the data and their correct type.
import Foundation
import MetalKit
// Creating the PlugType Enum
enum PlugType{
case Integer(Int?)
case Float_(Float?)
case Double_(Double?)
case Vector3(simd_int3)
// default types
static func IntegerType() -> PlugType{ return PlugType.Integer(nil)}
static func FloatType() -> PlugType{ return PlugType.Float_(nil)}
static func DoubleType() -> PlugType{ return PlugType.Double_(nil)}
}
// Implements a way to retrieve the correct value type
extension PlugType{
var IntegerValue: Int{
switch self{
case .Integer(let value):
return value ?? 0
default:
return 0
}
}
var FloatValue: Float{
switch self
{
case .Float_(let value):
return value ?? 0
default:
return 0
}
}
var DoubleValue: Double{
switch self
{
case .Double_(let value):
return value ?? 0
default:
return 0
}
}
}
// Get the string representation of the PlugType
extension PlugType {
var typeName: String{
switch self {
case .Integer: return "Integer"
case .Float_: return "Float"
case .Double_: return "Double"
case .Vector3: return "Vector3"
}
}
var swiftType: Any.Type {
switch self {
case .Integer: return Int.self
case .Float_: return Float.self
case .Double_: return Double.self
case .Vector3: return simd_int3.self
}
}
}
class Plug{
var _value:PlugType?
var type:String? { get{ return _value?.typeName } }
init(_ newValue:PlugType){
_value = newValue
}
func geee<T>(_ input:T) -> T{
switch type {
case "Integer":
return getVal(_value!.IntegerValue) as! T
case "Double":
return getVal(_value!.DoubleValue) as! T
default:
return 0 as! T
}
}
func getVal(_ val:Int) -> Int {
return val
}
func getVal(_ val:Float) -> Float {
return val
}
func getVal(_ val:Double) -> Double {
return val
}
}
var plugs:[Plug] = []
var p1 = Plug(PlugType.Integer(2))
I understand that it's a draft proposal. I tried to implement a simple DSL for building a string, like so:
#_functionBuilder
struct StringBuilder {
static func buildExpression(_ string: String) -> [String] {
[string]
}
static func buildBlock(_ children: [String]...) -> [String] {
children.flatMap{ $0 }
}
}
func s(separator: String = "", #StringBuilder _ makeString: () -> [String]) -> String {
makeString().joined(separator: separator)
}
let z = s(separator: " ") {
"this"
"is"
"cool"
}
However, the compiler complains that "'String' is not convertible to '[String]'". This leads me to believe that buildBlock is the only part of the proposal currently implemented. (This is understandable given that in SwiftUI they are building a hierarchy of views, so that's all they need.)
Is this correct or am I doing something wrong? What is the correct way to use buildExpression?
ielyamani's answer shows how to build a working string builder such as I used in my example above. However, that does not solve the actual problem. I'm not trying to build a string builder. I'm trying to figure out function builders. The string builder is just an example. For example, if we wish to have a string builder that accepts integers, we could in theory do the following:
#_functionBuilder
struct StringBuilder {
static func buildExpression(_ int: Int) -> [String] {
["\(int)"]
}
// The rest of it implemented just as above
}
In this case, when the compiler encountered an Int, it would call buildExpression to then spit out our component type, in this case [String]. But as Martin R said in a comment to this question, buildExpression is not currently implemented.
I encountered the same issue today, it seems that buildExpression isn't implemented. I ended up making a workaround by using a protocol "ComponentProtocol" and then creating "Expression: ComponentProtocol" and "Component: ComponentProtocol". That works for me for now. I am hoping it'll be implemented later.
protocol ComponentProtocol: ExpressibleByIntegerLiteral, ExpressibleByStringLiteral {
var value: String { get }
}
struct Expression: ComponentProtocol {
let _value: String
var value: String { _value }
init(_ value: String) { _value = value }
init(integerLiteral value: Int) { self.init(value) }
init(stringLiteral value: String) { self.init(value) }
init<E: CustomStringConvertible>(_ value: E) {_value = String(describing: value) }
}
struct Component: ComponentProtocol {
let _values: [String]
var value: String { _values.joined(separator: ", ") }
init(integerLiteral value: Int) { self.init(value) }
init(stringLiteral value: String) { self.init(value) }
init<E: CustomStringConvertible>(_ value: E) { _values = [String(describing: value)] }
init<T: ComponentProtocol>(_ values: T...) { _values = values.map { $0.value } }
init<T: ComponentProtocol>(_ values: [T]) { _values = values.map { $0.value } }
}
#_functionBuilder struct StringReduceBuilder {
static func buildBlock<T: ComponentProtocol>(_ components: T ...) -> Component { Component(components) }
static func buildEither<T: ComponentProtocol>(first: T) -> Component { Component(first.value) }
static func buildEither<T: ComponentProtocol>(second: T) -> Component { Component(second.value) }
static func buildOptional<T: ComponentProtocol>(_ component: T?) -> Component? {
component == nil ? nil : Component(component!.value)
}
}
func stringsReduce (#StringReduceBuilder block: () -> Component) -> Component {
return block()
}
let result = stringsReduce {
Expression(3)
"one"
Expression(5)
Expression("2")
83
}
let s2 = stringsReduce {
if .random () { // random value Bool
Expression(11)
} else {
Expression("another one")
}
}
Since buildBlock(_:) takes a variadic number of arrays of strings, this would work:
let z = s(separator: " ") {
["this"]
["is"]
["cool"]
}
But that's still clunky. To take strings instead of Arrays of strings, add this function to StringBuilder which takes a variable number of strings:
static func buildBlock(_ strings: String...) -> [String] {
Array(strings)
}
And now you can do this:
let z = s(separator: " ") {
"Hello"
"my"
"friend!"
}
print(z) //Hello my friend!
** REWRITE **
OK, it turns out I'm really asking a different question. I understand about hashValue and ==, so that's not relevant.
I would like my wrapper class BUUID to "do the right thing" and act just like NSUUID's act in a Dictionary.
See below, where they don't.
import Foundation
class BUUID: NSObject {
init?(str: String) {
if let uuid = NSUUID(UUIDString: str) {
_realUUID = uuid
}
else {
return nil
}
}
override init() {
_realUUID = NSUUID()
}
private var _realUUID: NSUUID
override var description: String { get { return _realUUID.UUIDString } }
override var hashValue: Int { get { return _realUUID.hashValue } }
var UUIDString: String { get { print("WARNING Use description or .str instead"); return _realUUID.UUIDString } }
var str: String { get { return _realUUID.UUIDString } }
}
func ==(lhs: BUUID, rhs: BUUID) -> Bool { return lhs._realUUID == rhs._realUUID }
let a = BUUID()
let b = BUUID(str: a.str)!
print("a: \(a)\nb: \(b)")
print("a === b: \(a === b)")
print("a == b: \(a == b)")
var d = [a: "Hi"]
print("\(d[a]) \(d[b])")
let nA = NSUUID()
let nB = NSUUID(UUIDString: nA.UUIDString)!
print("na: \(nA)\nnB: \(nB)")
print("nA === nB: \(nA === nB)")
print("nA == nB: \(nA == nB)")
var nD = [nA: "Hi"]
print("\(nD[nA]) \(nD[nB])")
Results. Note that I can look up using NSUUID nB and get back what I put under nA. Not so with my BUUID.
a: 9DE6FE91-D4B5-4A6B-B912-5AAF34DB41C8
b: 9DE6FE91-D4B5-4A6B-B912-5AAF34DB41C8
a === b: false
a == b: true
Optional("Hi") nil
nA: <__NSConcreteUUID 0x7fa193c39500> BB9F9851-93CF-4263-B98A-5015810E4286
nB: <__NSConcreteUUID 0x7fa193c37dd0> BB9F9851-93CF-4263-B98A-5015810E4286
nA === nB: false
nA == nB: true
Optional("Hi") Optional("Hi")
Inheriting from NSObject also assumes isEqual(object: AnyObject?) -> Bool method overloading:
import Foundation
class BUUID: NSObject {
init?(str: String) {
if let uuid = NSUUID(UUIDString: str) {
_realUUID = uuid
}
else {
return nil
}
}
override init() {
_realUUID = NSUUID()
}
private var _realUUID: NSUUID
override func isEqual(object: AnyObject?) -> Bool {
guard let buuid = object as? BUUID else {
return false
}
return buuid._realUUID == _realUUID
}
override var description: String { get { return _realUUID.UUIDString } }
override var hashValue: Int { get { return _realUUID.hashValue } }
var UUIDString: String { get { print("WARNING Use description or .str instead"); return _realUUID.UUIDString } }
var str: String { get { return _realUUID.UUIDString } }
}
func ==(lhs: BUUID, rhs: BUUID) -> Bool { return lhs._realUUID == rhs._realUUID }
let a = BUUID()
let b = BUUID(str: a.str)!
print("a: \(a)\nb: \(b)")
print("a === b: \(a === b)")
print("a == b: \(a == b)")
var d = [a: "Hi"]
print("\(d[a]) \(d[b])")
let nA = NSUUID()
let nB = NSUUID(UUIDString: nA.UUIDString)!
print("na: \(nA)\nnB: \(nB)")
print("nA === nB: \(nA === nB)")
print("nA == nB: \(nA == nB)")
var nD = [nA: "Hi"]
print("\(nD[nA]) \(nD[nB])")
So the answer is to not make BUUID inherit from NSObject, which undercuts the Swiftiness of overriding ==.
So:
extension BUUID: Hashable {}
class BUUID: CustomStringConvertible {
// take away all 'override' keywords, nothing to override
// otherwise same as above
}
Interesting!
This answer is relevant to initially asked question: Why that's possible to get two key-value pairs with identical key's hashes in a dictionary
This example illustrates that keys in Dictionary can have identical hashes, but equality operation should return false for different keys:
func ==(lhs: FooKey, rhs: FooKey) -> Bool {
return unsafeAddressOf(lhs) == unsafeAddressOf(rhs)
}
class FooKey: Hashable, Equatable {
var hashValue: Int {
get {
return 123
}
}
}
var d = Dictionary<FooKey, String>()
let key1 = FooKey()
let key2 = FooKey()
d[key1] = "value1"
d[key2] = "value2"
Output
[FooKey: "value1", FooKey: "value2"]
That's definitely not good to have all keys with the same hash. In this case we are getting that worst case when search element complexity fells down to O(n) (exhaustive search). But it will work.
In Swift (a language I'm still fairly new to), I'm trying to define a class that allows indexing using either an Int or Range<Int>. For example:
var m = Matrix(rows: 10, cols: 10)
var v = m[1, 0..<10]
The two ways I can think of allowing this issue is to either adding an extension to the Range class:
extension Range {
init(_ intValue:Element) {
self.init(start: intValue, end: intValue.successor())
}
}
or to create an enum that allows for either type:
enum IndexType {
case value(Int)
case range(Range<Int>)
init(_ v:Int) {
self = .value(v)
}
init(_ r:Range<Int>) {
self = .range(r)
}
}
However, neither solution works as intended, as I still need to specify the type manually. For example, given the function:
func slice(indices:IndexType...) -> [Double] {
// ...
}
I can't then just do:
slice(1, 3...4, 5)
but instead have to do:
slice(IndexType(1), IndexType(3...4), 5)
Is there a way to accomplish this in Swift? I'm used to c++, which would do type inference automatically, but the same doesn't appear to work with Swift.
One similar question I found was:
Swift Arrays of Multiple Types
However, I really would like to avoid the use of Any as I know the two types it should be.
protocol MatrixIndex {
var Matrix_range: Range<Int> { get }
}
extension Int : MatrixIndex {
var Matrix_range: Range<Int> {
get {
return Range<Int>(start: self, end: self+1)
}
}
}
extension Range : MatrixIndex {
var Matrix_range: Range<Int> {
get {
return Range<Int>(start: self.startIndex as! Int, end: self.endIndex as! Int)
}
}
}
class Matrix {
subscript(row: MatrixIndex, column: MatrixIndex) -> () {
get {
print("getting \(row.Matrix_range) \(column.Matrix_range)")
}
set(newValue) {
print("setting \(row.Matrix_range) \(column.Matrix_range)")
}
}
}
The following example is taken from Apple Swift Reference guide. I only added the getHasAreaInstances() and getGenericHasAreaInstances()
import UIKit
#objc protocol HasArea {
var area: Double { get }
}
#objc protocol HasExtendedArea: HasArea {
var extendedArea: Double { get }
}
class Circle: HasArea {
let pi = 3.1415927
var radius: Double
var area: Double { return pi * radius * radius }
init(radius: Double) { self.radius = radius }
}
class Country: HasArea {
var area: Double
init(area: Double) { self.area = area }
}
class Continent: HasExtendedArea {
var area: Double { return 300 }
var extendedArea: Double { return 3000 }
}
let objects: [HasArea] = [
Circle(radius: 2.0),
Country(area: 243_610),
Continent()
]
for object in objects {
if let objectWithArea = object as? HasExtendedArea {
println("Extended Area is \(objectWithArea.area)")
} else {
println("Area is not extended")
}
}
// Extended Area is 300.0
// Area is not extended
// Area is not extended
The method below returns the correct array:
func getHasExtendedAreaInstances() -> [HasExtendedArea] {
var haveArea: [HasExtendedArea] = []
for object in objects {
if let objectWithArea = object as? HasExtendedArea {
haveArea.append(objectWithArea)
}
}
return haveArea
}
let areas = getHasExtendedAreaInstances()
//[Continent]
The method below returns the correct array:
func getGenericHasExtendedAreaInstances<T>() -> [T] {
var haveArea: [T] = []
for object in objects {
if let objectWithArea = object as? T {
haveArea.append(objectWithArea)
}
}
return haveArea
}
let areasGeneric: [HasExtendedArea] = getGenericHasExtendedAreaInstances()
//[Continent]
However, as soon as a constraint is imposed on the generic type, it no longer works
func getGenericConstraintHasExtendedAreaInstances<T: HasArea>() -> [T] {
var haveArea: [T] = []
for object in objects {
if let objectWithArea = object as? T {
// the line above fails with swift_dynamicCastUnknownClass
haveArea.append(objectWithArea)
}
}
return haveArea
}
let areasGenericConstraint: [HasExtendedArea] = getGenericConstraintHasExtendedAreaInstances()
Your generic function makes no sense. What would resolve it? What would satisfy it? Make a simpler example with the same basic declaration structure: it's an impossible function. For example, start with this nongeneric function:
class Thing : Printable {
var description : String {return "thing"}
}
func g() -> [Thing] {
return [Thing()]
}
let result : [Thing] = g()
Now modify g to be generic, exactly parallel to your function:
class Thing : Printable {
var description : String {return "thing"}
}
func g<T:Printable>() -> [T] {
return [Thing()]
}
let result : [Thing] = g()
It doesn't compile - because it makes no sense.
This is fixed in Swift 1.2, tested on Xcode 6.3 Beta 3
You can specify the type constraint without swift compiler failing on you