Swift, Protocols and Generics in Genetic Algorithm - swift

I am trying to switch from Java to Swift and improve my programming skills in this language.
However, I have some difficulties understanding how generics works in Swift after a study of:
https://docs.swift.org/swift-book/LanguageGuide/Generics.html
I have started to write a genetic algorithm by writing some protocols.
protocol Point : Equatable {
var identifier: String { get }
var x: Double { get }
var y: Double { get }
func distance<P : Point>(to point: P) -> Double
}
protocol Individual {
associatedtype P : Point
var fitness: Double { get }
var chromosomes: [P] { get }
}
and now I want to make a struct which conforms to the Individual protocol.
The only try that compiles is
struct Route : Individual {
typealias P = City;
var fitness: Double { 0.0 }
var chromosomes: [City]
}
However, I want to make Route as much as generic, therefore I don't want to tell that it uses City as implementation of Point. I want that Route knows that it works on array of objects which conforms to Point protocol.
I'd appreciate your help.
Thank you in advance.

First of all, I'd suggest adding a Self requirement on the distance(to:) method. Self just tells the compiler that the paremeter is the same type as the conforming type.
protocol Point : Equatable {
var identifier: String { get }
var x: Double { get }
var y: Double { get }
func distance(to point: Self) -> Double
}
So, in your City struct point must also be of type City.
struct City: Point {
var identifier: String
var x: Double
var y: Double
func distance(to point: City) -> Double {
return .zero
}
}
You can make your Route struct more flexible by adding a generic parameter that also satisfies the associated type requirement imposed by the Individual protocol.
struct Route<P: Point>: Individual {
var fitness: Double { 0.0 }
var chromosomes: [P]
}
To instantiate a Route:
var cityRoute = Route<City>(chromosomes: [])

You can create an array of class that implements a specific protocol, so for example in this case you will have:
struct Route: Individual {
typealias P = City;
var fitness: Double { 0.0 }
var chromosomes: [Point]
}
and you can call all the protocol methods.

Related

Swift generics for graph classes

I'm trying to create some classes in Swift 5 to represent a directed Graph. I'm finding Swift generics to be very confusing and restrictive.
This is what I've got so far, but no matter what I try, Swift seems to come up with some obscure error or other (two are shown below in comments).
Can I even achieve this kind of structure in Swift without hardcoding Node to a specific concrete type?
I want to allow the Node type to be changed, so that I can add additional properties to the Node and Edge types according to the needs of the problem.
public class Graph<N:Node>
{
var nodeMap: [String: N] = [:]
var edges: [Edge<N>] = []
public func addEdge(_ parentName: String, _ childName: String, weight: Double = 0.0) throws {
let parent:N? = nodeMap[parentName]
let child:N? = nodeMap[childName]
let newEdge = Edge(parent!, child!)
parent!.outgoing.append(newEdge) // Cannot convert value of type 'Edge<N>' to expected argument type 'Edge<Node>'
edges.append(newEdge)
}
}
public class Edge<N:Node> {
var parent: N
var child: N
init(_ parent: N, _ child: N) {
self.parent = parent
self.child = child
}
}
public class Node {
var name:String = ""
var outgoing:[Edge<Self.Type>] = [] //'Edge' requires that 'Self.Type' inherit from 'Node'
}
I guess I'm a bit late to the party but for any future readers, the Final "issue" can be solved by making the Edge a protocol as well:
protocol Edge: class {
associatedtype NodeType: Node where NodeType.EdgeType == Self
var parent: NodeType {get set}
var child: NodeType? {get set}
}
To make sure any classes implementing these protocols actually point to the correct counterpart I've added a type constraint on the associatedtype.
protocol Node: class {
associatedtype EdgeType: Edge where EdgeType.NodeType == Self
var name:String {get set}
var outgoing:[EdgeType] {get set}
}
Just be careful of strong reference cycles as pointed out earlier. Hence the optional type of Edge.child to allow it to be weak. The reference arrangement can off course be different.
The main caveat of this method is that any subclasses to classes implementing these protocols will have properties pointing to their superclass. A proposed solution would be to not subclass but implement the protocols directly on the new class instead.
I think you need to make Node a protocol:
public protocol Node : class {
var name:String { get set }
var outgoing:[Edge<Self>] { get set }
}
Then, you can create concrete Node conformers that you can use as the generic argument for graph. e.g.
final public class ConcreteNode: Node {
public var name = ""
public var outgoing: [Edge<ConcreteNode>] = []
}
And you can create a Graph<ConcreteNode>. If you want to have a node with a foo property, you can create that class too:
final public class NodeWithFoo: Node {
public var name = ""
public var outgoing: [Edge<NodeWithFoo>] = []
public var foo = ""
}
And you can have another Graph<NodeWithFoo>.
Thanks for the responses.
The real end goal of this was to have Node and Edge types that could be specialized with additional fields to suit the application.
Sweeper's answer was a good answer to the specific implementation I posted in the question, and I learned a lot from it, so thanks for that.
However, what I ended up going with didn't use generics at all. This is what I did instead:
public class Node {
var name:String = ""
var outgoing:[Edge] = []
// Added this catchall property here
var data: Any?
}
I did a similar thing in the Edge class.
Now when I want to add some data to a Node, like say the price of an item as a Double field for example, I can simply create an extension like this:
extension Node {
var price:Double? {
get {
return self.data as? Double
}
set {
self.data = newValue
}
}
}
If I need to add more fields, I can always wrap them in a struct or class and set that via the extension.

Swift protocol using another protocol causes error

I'm working in Swift 4.
I want to define a Problem.
A Problem consists of a Question and an Answer.
The Question might be any of: String, Int, [Int], Image, [Image] or some new Type not defined or could be some combination of the above.
The Answer might also be any of the above but a given Question can have an Answer of a different type.
(e.g. question = (Image, "What type of animal is this?), answer = ("A Cat") )
So I thought protocols would be the way to go:
protocol Posable {
var pose: String { get }
}
protocol Answerable: Hashable {
var answer: String { get }
}
protocol Puzzle {
var problem: Posable { get }
var solution: Answerable { get }
}
I made Answerable Hashable because I want to be able to compare Answers and create sets of Answers.
But I get on the solution: Answerable line:
'Protocol 'Answerable' can only be used as a generic constraint because it has Self or associated type requirements.
I understand why that is but...
Can anyone make any suggestions about how to implement this so that I don't run into that problem?
I'm keen to implement with protocols if possible, partly so that I learn about them.
I would solve it with generics :
import UIKit
struct Posable<T> {
var pose: T
}
struct Answerable<T> {
var answer: T
}
extension Answerable: Equatable where T: Equatable {
static func ==(lhs: Answerable<T>, rhs: Answerable<T>) -> Bool {
return lhs.answer == rhs.answer
}
}
extension Answerable: Hashable where T: Hashable {
var hashValue: Int {
return answer.hashValue
}
}
struct Puzzle<T, U> {
var problem: Posable<T>
var solution: Answerable<U>
}
let image = UIImage() // Image of a cat
let pose = Posable<(UIImage, String)>(pose: (image, "What type of animal is this?"))
let solution = Answerable<String>(answer: "A cat")
let myPuzzle = Puzzle<(UIImage, String), String>(problem: pose, solution: solution)
Generics allow you to make very reusable code! Here you can use any class as a question or as an anwser.
With Swift type inherence : you also get to simplify the initialization :
let image = UIImage() // Image of a cat
let pose = Posable(pose: (image, "What type of animal is this?"))
let solution = Answerable(answer: "A cat")
let myPuzzle = Puzzle(problem: pose, solution: solution)
I'm not sure but you can remove Hashable from Answerable.
protocol Posable {
var pose: String { get }
}
protocol Answerable {
var answer: String { get }
}
protocol Puzzle {
var problem: Posable? { get }
func getSolution<T: Hashable & Answerable>() -> T
}

Swift associatedType from protocol type - how to do that?

I'm having issues using associated type as protocol:
protocol Searchable{
func matches(text: String) -> Bool
}
protocol ArticleProtocol: Searchable {
var title: String {get set}
}
extension ArticleProtocol {
func matches(text: String) -> Bool {
return title.containsString(text)
}
}
struct FirstArticle: ArticleProtocol {
var title: String = ""
}
struct SecondArticle: ArticleProtocol {
var title: String = ""
}
protocol SearchResultsProtocol: class {
associatedtype T: Searchable
}
When I try to implement search results protocol, I get compile issue:
"type SearchArticles does not conform to protocol SearchResultsProtocol"
class SearchArticles: SearchResultsProtocol {
typealias T = ArticleProtocol
}
As I understand, it happens because T in SearchArticles class is not from concrete type (struct in that example), but from protocol type.
Is there a way to solve this issue?
Thanks in advance!
An associatedtype is not meant to be a placeholder (protocol), it is meant to be a concrete type. By adding a generic to the class declaration you can achieve the same result you want like this....
class SearchArticles<V: ArticleProtocol>: SearchResultsProtocol {
typealias T = V
}
Then, as you use SearchArticles around your app, you can declare let foo = SearchArticles<FirstArticle> or let foo = SearchArticles<SecondArticle>

Mapping in Swift Between Protocol Conforming Types

I want to map between any two objects which conform to the same protocol. It would be convenient to do so via a function with the signature:
func mapFrom<T>(objectA: T, to inout objectB: T)
Even better though (for immutable types) would be to have it in the form:
func map<T, U: T>(from source: T) -> U
where somehow it could initialize a U object from the values in T.
I would like to do this via Swift Reflection rather than using the Objective-C run-time, but I would settle for that if it was the only way. If somehow it could be done without reflection that would be amazing, but I don't see how.
The reason I want to do this is because I have mutable Realm classes which conform to their respective protocol, and I want to map them to the immutable struct types.
An example would be:
/**
The protocol.
*/
protocol Food {
var name: String { get }
var weight: Float { get }
var price: Float { get }
}
/**
The mutable Realm class representation.
*/
final class FoodEntity: Object, Food {
dynamic var name = ""
dynamic var weight = 0.0
dynamic var price = 0.0
}
/**
The final struct I want to map to from the Realm representation.
*/
struct FoodProduct: Food {
let name: String
let weight: Float
let price: Float
}
I would like to be able to have a generic function or method with which to map a FoodEntity to a FoodProduct without having to manually do something like:
FoodProduct(name: entity.name, weight: entity.weight, price: entity.price)
How can this be done, if it can be done at all?
I think you are looking for something like this.
func fetchAllFoodProducts() -> [FoodProduct]
{
var foodProducts : [FoodProduct] = []
// Fetch From Realm
let products = realm.objects(FoodEntity.self)
for product in products
{
foodProducts.append(FoodProduct(name: product.name, weight: product.weight, price: product.price))
}
return foodProducts
}
The thing is that there can't be a generic way to do this. Because you have to assign the values of name, weight & price somehow. This is the closest you can get, I think.
Or you can do something like this.
func fetchAllFoodProducts() -> [FoodProduct]
{
var foodProducts : [FoodProduct] = []
// Fetch From Realm
let products = realm.objects(FoodEntity.self)
for product in products
{
foodProducts.append(FoodProduct(entity: product))
}
return foodProducts
}
By altering your FoodEntity a little.
struct FoodProduct: Food {
let name: String
let weight: Float
let price: Float
init(entity : FoodEntity)
{
self.name = entity.name
self.weight = entity.weight
self.price = entity.price
}
}

How to define initializers in a protocol extension?

protocol Car {
var wheels : Int { get set}
init(wheels: Int)
}
extension Car {
init(wheels: Int) {
self.wheels = wheels
}
}
on self.wheels = wheels i get the error
Error: variable 'self' passed by reference before being initialized
How can I define the initializer in the protocol extension?
As you can see this doesn't work under these circumstances because when compiling, one has to make sure that all properties are initialized before using the struct/enum/class.
You can make another initializer a requirement so the compiler knows that all properties are initialized:
protocol Car {
var wheels : Int { get set }
// make another initializer
// (which you probably don't want to provide a default implementation)
// a protocol requirement. Care about recursive initializer calls :)
init()
init(wheels: Int)
}
extension Car {
// now you can provide a default implementation
init(wheels: Int) {
self.init()
self.wheels = wheels
}
}
// example usage
// mark as final
final class HoverCar: Car {
var wheels = 0
init() {}
}
let drivableHoverCar = HoverCar(wheels: 4)
drivableHoverCar.wheels // 4
As of Xcode 7.3 beta 1 it works with structs as expected but not with classes since if they are not final the init(wheels: Int) in the protocol is a required init and it can be overridden therefore it cannot be added through an extension. Workaround (as the complier suggests): Make the class final.
Another workaround (in depth; without final class)
To work with classes without making them final you can also drop the init(wheels: Int) requirement in the protocol. It seems that it behaves no different than before but consider this code:
protocol Car {
var wheels : Int { get set }
init()
// there is no init(wheels: Int)
}
extension Car {
init(wheels: Int) {
self.init()
print("Extension")
self.wheels = wheels
}
}
class HoverCar: Car {
var wheels = 0
required init() {}
init(wheels: Int) {
print("HoverCar")
self.wheels = wheels
}
}
// prints "HoverCar"
let drivableHoverCar = HoverCar(wheels: 4)
func makeNewCarFromCar<T: Car>(car: T) -> T {
return T(wheels: car.wheels)
}
// prints "Extension"
makeNewCarFromCar(drivableHoverCar)
So if you make a Car from a generic context where the type on which you call init is only to be known as Car the extension initializer is called even though an initializer is defined in HoverCar. This only occurs because there is no init(wheels: Int) requirement in the protocol.
If you add it you have the former problem with declaring the class as final but now it prints two times "HoverCar". Either way the second problem probably never occurs so it might be a better solution.
Sidenote: If I have made some mistakes (code, language, grammar,...) you're welcome to correct me :)
My understanding is that this isn't possible, because the protocol extension can't know which properties the conforming class or struct has - and therefore cannot guarantee they are correctly initialized.
If there are ways to get around this, I'm very interested to know! :)
#Qbyte is correct.
In addition, you can take a look at my Configurable
In that I have Initable protocol
public protocol Initable {
// To make init in protocol extension work
init()
}
public extension Initable {
public init(#noescape block: Self -> Void) {
self.init()
block(self)
}
}
Then in order to conform to it
extension Robot: Initable { }
I have 2 ways, using final or implement init
final class Robot {
var name: String?
var cute = false
}
class Robot {
var name: String?
var cute = false
required init() {
}
}
May not be the same but in my case instead of using init I used a static func to return the object of the class.
protocol Serializable {
static func object(fromJSON json:JSON) -> AnyObject?
}
class User {
let name:String
init(name:String) {
self.name = name
}
}
extension User:Serializable {
static func object(fromJSON json:JSON) -> AnyObject? {
guard let name = json["name"] else {
return nil
}
return User(name:name)
}
}
Then to create the object I do something like:
let user = User.object(fromJSON:json) as? User
I know its not the best thing ever but its the best solution I could find to not couple business model with the data layer.
NOTE: I'm lazy and I coded everything directly in the comment so if something doesn't work let me know.