return nil or something similar in method stub - swift

I am taking a data structures in java course and for fun and learning I am trying to write the stuff in Swift. I am trying to implement a protocol but I am having trouble setting up the method stubs. I tried returning nil but that didn't work but now I am getting this error:
"Swift Compiler Error 'E' is not convertible to 'E'"
That is strange. This is code for a generic array based list. This is what I have so far:
struct ArrayLinearList<E>: LinearListADT {
let DEFAULT_MAX_SIZE = 100;
var currentSize: Int
var maxSize: Int
var storage = [E]()
init(sizeOfList: Int) {
currentSize = 0
maxSize = sizeOfList
storage = [E]()
}
mutating func addFirst<E>(obj: E) {
}
mutating func addLast<E>(obj: E) {
}
mutating func insert<E>(obj: E, location: Int) {
}
mutating func remove<E>(location: Int) -> E {
return storage[location] //***This is where I get the above error
}
mutating func remove<E>(obj: E) -> E {
return nil //I tried this but that didn't work either
}
mutating func removeFirst<E>() -> E? {
return nil //I also tried this but that didn't work
}
mutating func removeLast<E>() -> E? {
return nil
}
mutating func get<E>(location: Int) -> E? {
return nil
}
mutating func contains<E>(obj: E) -> Bool {
return false
}
mutating func locate<E>(obj: E) -> Int? {
return nil
}
mutating func clear<E>() {
}
mutating func isEmpty<E>() -> Bool {
}
mutating func size<E>() -> Int {
}
}
EDIT: I just found the mistake. Using the suggestion from Jesper I then found out that I did not write the protocol properly in Swift. Looking at this answer"
how to create generic protocols in swift iOS?
I was able to get it working now. Thank you Jesper!

You shouldn't have a type parameter E on those methods - it will be considered a separate type parameter from the one on the struct. Remove the <E> in those method definitions and the one from the struct itself will be used.
In addition, you may have to add a constraint to E so that you are sure that it implements NilLiteralConvertible (like an Optional), otherwise you can't return nil from a function that is supposed to return a E.

I just found the mistake. Using the suggestion from Jesper I then found out that I did not write the protocol properly in Swift. Looking at this answer"
How to create generic protocols in Swift?
I was able to get it working now. Thank you Jesper!

Related

Returning an object that conforms to a generic constraint

I am trying to create a Builder for my ComplexObject:
import Foundation
class ComplexObject {
// lots of stuff
init<ObjectType, T>(_ closure: ((ObjectType) -> T)) {
// lots of init/setup code
}
// other initializers with generics, constructed
// by other Builders than ConcreteBuilder<O> below
}
protocol BuilderType {
associatedtype ObjectType
func title(_: String) -> Self
func build<T>(_ closure: ((ObjectType) -> T)) -> ComplexObject
}
struct Injected<O> {
//...
}
extension ComplexObject {
static func newBuilder<Builder: BuilderType, O>(someDependency: Injected<O>) -> Builder where Builder.ObjectType == O {
// vvvv
return ConcreteBuilder(someDependency: someDependency)
// ^^^^
// Cannot convert return expression of type 'ComplexObject.ConcreteBuilder<O>' to return type 'Builder'
}
struct ConcreteBuilder<O>: BuilderType {
private let dependency: Injected<O>
private var title: String
init(someDependency: Injected<O>) {
self.dependency = someDependency
}
func title(_ title: String) -> ConcreteBuilder<O> {
var builder = self
builder.title = title
return builder
}
func build<T>(_ closure: ((O) -> T)) -> ComplexObject {
return ComplexObject(closure)
}
}
}
but swiftc complains about the return ConcreteBuilder(...) line
Cannot convert return expression of type 'ComplexObject.ConcreteBuilder<O>' to return type 'Builder'
I also tried
static func newBuilder<Builder: BuilderType>(someDependency: Injected<Builder.ObjectType>) -> Builder {
return ConcreteBuilder(someDependency: someDependency)
}
with the same result. I see that I could just expose ConcreteBuilder, but I hoped to be able to hide that implementation detail. What am I missing here?
I'm not sure how to solve this issue, but the root of the problem is that newBuilder(someDependancy:) has a generic type signature, but it's really not generic.
Its return type asserts that function can return an object of any type T: BuilderType where Builder.ObjectType == O, but that's clearly not the case. Asking this function to return any type besides a ConcreteBuilder isn't supported. At best, you could use a force cast, but if someone writes let myBuilder: MyBuilder = ComplexObject.newBuilder(someDependancy: dec), the code would crash (even if MyBuilder satisfies your generic constraints) because you're trying to force cast ConcreteBuilder to MyBuilder.
As far as a solution... I don't have one. Fundamentally you just want to return BuilderType, but I don't think that's possible because it has an associated type.
Will this do ?
return ConcreteBuilder(someDependency: someDependency) as! Builder

Is it possible to have a same collection instance in a dictionary associated with multiple keys in swift?

I have a Set instance and want to put it into a Dictionary, and associate it with multiple keys so I can lookup/modify it in the future.
Following Python code is what I want to achieve in Swift.
s = set()
D = {}
D["a"] = s
D["b"] = s
D["a"].add("Hello")
D["a"].add("World")
print(D["b"]) # getting {"Hello", "World"} back
I tried something like following in Swift.
var s = Set<String>()
var D = Dictionary<String, Set<String>>()
D["a"] = s // copy of s is assigned
D["b"] = s // another copy of s is assigned
D["a"]!.insert("Hello")
D["a"]!.insert("World")
print(D["b"]!) // empty :(
Since collections in Swift hold value semantics, by the time I put a set into a dictionary, new instance is created. Is there any workaround? I know I could use NSMutableSet instead of Swift's Set, but I want to know how I can approach this by using collections with value semantics if possible.
Ah! Now we get to the heart of it. You just want a reference type based on stdlib rather than using the one that Foundation gives you. That's straightforward to implement, if slightly tedious. Just wrap a Set in a class. If you don't want full SetAlgebra or Collection conformance, you don't have to implement all of these methods. (And you might want some more init methods to make this more convenient, but hopefully those implementations are fairly obvious from your code needs.)
final class RefSet<Element> where Element: Hashable {
private var storage: Set<Element> = Set()
init() {}
}
extension RefSet: Equatable where Element: Equatable {
static func == (lhs: RefSet<Element>, rhs: RefSet<Element>) -> Bool {
return lhs.storage == rhs.storage
}
}
extension RefSet: SetAlgebra {
var isEmpty: Bool { return storage.isEmpty }
func contains(_ member: Element) -> Bool {
return storage.contains(member)
}
func union(_ other: RefSet<Element>) -> RefSet<Element> {
return RefSet(storage.union(other.storage))
}
func intersection(_ other: RefSet<Element>) -> RefSet<Element> {
return RefSet(storage.intersection(other.storage))
}
func symmetricDifference(_ other: RefSet<Element>) -> RefSet<Element> {
return RefSet(storage.symmetricDifference(other.storage))
}
#discardableResult
func insert(_ newMember: Element) -> (inserted: Bool, memberAfterInsert: Element) {
return storage.insert(newMember)
}
#discardableResult
func remove(_ member: Element) -> Element? {
return storage.remove(member)
}
#discardableResult
func update(with newMember: Element) -> Element? {
return storage.update(with: newMember)
}
func formUnion(_ other: RefSet<Element>) {
storage.formUnion(other.storage)
}
func formIntersection(_ other: RefSet<Element>) {
storage.formIntersection(other.storage)
}
func formSymmetricDifference(_ other: RefSet<Element>) {
storage.formSymmetricDifference(other.storage)
}
}
extension RefSet: Collection {
typealias Index = Set<Element>.Index
var startIndex: Index { return storage.startIndex }
var endIndex: Index { return storage.endIndex }
subscript(position: Index) -> Element {
return storage[position]
}
func index(after i: Index) -> Index {
return storage.index(after: i)
}
}

Swift type erasure - for this case?

I have requirement of implementing TypeConverter and later use it as variable type. Inspired by ObjectMapper I have defined following protocol:
protocol TypeConverter {
associatedtype A
associatedtype B
func transformFrom(fromType: A?) -> B?
func transformTo(toType: B?) -> A?
}
Concrete implementation is:
class IntToStringTypeConverter: TypeConverter {
typealias A = Int
typealias B = String
func transformFrom(fromType: Int?) -> String? {
guard let fromType = fromType else { return nil }
return String(fromType)
}
func transformTo(toType: String?) -> Int? {
guard let toType = toType else { return nil }
return Int(toType)
}
}
Because protocol TypeConverter has associatedtype, I cannot declare it as variable, for example: var converter: TypeConverter, but I need such feature. The solution to such case is using typeErasure. By following this link https://medium.com/#NilStack/swift-world-type-erasure-5b720bc0318a it should be possible, but I don't have real idea how.
Here is my try, but its not right :)... Is this even solve-able this way? Or I should use this one: https://appventure.me/2017/12/10/patterns-for-working-with-associated-types ?
class AnyTypeConverter<Y, Z>: TypeConverter {
typealias A = Y
typealias B = Z
private let _transformFrom: (Z?) -> Y?
private let _transformTo: (Y?) -> Z?
init<W: TypeConverter>(_ iFormTypeConverter: W) where W.A == Y, W.B == Z {
self._transformFrom = iFormTypeConverter.transformFrom
self._transformTo = iFormTypeConverter.transformTo
}
func transformFrom(modelType: Y?) -> Z? {
return transformFrom(modelType: modelType)
}
func transformTo(iFormType: Z?) -> Y? {
return transformTo(iFormType: iFormType)
}
}
This is not really a good use for a protocol with associated types. PATs are very complicated tools, and there's really no reason for it in this case at all. You don't even need a type-eraser so much as just a struct:
struct TypeConverter<Model, Form> {
let transformFrom: (Model) -> Form?
let transformTo: (Form) -> Model?
}
let stringToInt = TypeConverter(transformFrom:String.init,
transformTo:Int.init)
stringToInt.transformFrom(123)
stringToInt.transformTo("x")
You of course could make this conform to TypeConverter if you wanted to (and I can update to add that), but I recommend dropping the protocol entirely and just using structs. This is very close to how Formatter works.
After implementing two cells I have found out that I can simplify this thing a bit, and go with only one associated type :). The type used in the cell is actually defined by the UI component - if there is UITextField, then type will be String, if I implement custom stepper, it will be Int (for example). If I want to make my cell generic, then it should work with Any type, for which I can write converter between model and (pre)defined cellType.
protocol FormTypeConverter {
associatedtype FormType
func fromModelToForm(_ value: Any?) -> FormType?
func fromFormToModel(_ value: FormType?) -> Any?
}
With that I can use simple type erasure as follows (source in links in the first post)
struct AnyFormTypeConverter<T>: FormTypeConverter {
// MARK: - Variables
private let fromModelToFormWrapper: (Any?) -> T?
private let fromFormToModelWrapper: (T?) -> Any?
init<Y: FormTypeConverter>(_ formTypeConverter: Y) where Y.FormType == T {
self.fromModelToFormWrapper = formTypeConverter.fromModelToForm
self.fromFormToModelWrapper = formTypeConverter.fromFormToModel
}
func fromModelToForm(_ value: Any?) -> T? {
return fromModelToFormWrapper(value)
}
func fromFormToModel(_ value: T?) -> Any? {
return fromFormToModel(value)
}
}
This case implementation suits excellent. Already implemented two completely different forms in no-time :)

Can I specialize a generic method implementation in Swift?

I would like to implement a generic function in two ways, one of them specialized to a specific generic value, but so far I was not able to express this in Swift 3.
My setup is like this:
protocol Convertible {
func convert<T>() -> Converted<T>
}
struct Unconverted: Convertible {
func convert<T>() -> Converted<T> {
return Converted<T>()
}
}
struct Converted<T>: Convertible {
func convert<T2>() -> Converted<T2> {
return Converted<T2>()
}
}
What I would like to achieve is to add a special case for convert() on Converted<T>, for the case where T2 == T, so the following behavior is achieved:
let unconverted: Convertible = Unconverted()
let converted: Convertible = unconverted.convert() as Converted<String>
// double conversion to same generic type is ok, should ideally return self
let convertedOk = converted.convert() as Converted<String>
// re-conversion to another type is not ok and should fail
let convertedFail = converted.convert() as Converted<Int>
I tried the following approaches, but none of them worked out:
struct Converted<T> {
func convert<T2>() -> Converted<T2> {
fatalError("already converted")
}
// error: Same-type requirement makes generic parameters 'T2' and 'T' equivalent
func convert<T2>() -> Converted<T2> where T2 == T {
return self
}
}
struct Converted<T> {
func convert<T2>() -> Converted<T2> {
fatalError("already converted")
}
// method is never called, even when T2 == T
func convert() -> Converted<T> {
return self
}
}
struct Converted<T> {
func convert<T2>() -> Converted<T2> {
// does not call the specialized method, even when T2 == T
self.internalConvert(type: T2.self)
}
private func internalConvert<T2>(type: T2.Type) -> Converted<T2> {
fatalError("already converted")
}
private func internalConvert(type: T.Type) -> Converted<T> {
return self
}
}
Is there a way to express this?

How to create an array of instances of a subclass from a superclass

From this answer, I know that I can create an instance of a subclass from a superclass. Yet, I can't figure out how to create an array of the subclass from the superclass.
Drawing on the above example, here's my best shot so far:
class Calculator {
func showKind() { println("regular") }
required init() {}
}
class ScientificCalculator: Calculator {
let model: String = "HP-15C"
override func showKind() { println("\(model) - Scientific") }
required init() {
super.init()
}
}
extension Calculator {
class func createMultiple<T:Calculator>(num: Int) -> T {
let subclass: T.Type = T.self
var calculators = [subclass]()
for i in 0..<num {
calculators.append(subclass())
}
return calculators
}
}
let scis: [ScientificCalculator] = ScientificCalculator.createMultiple(2)
for sci in scis {
sci.showKind()
}
With that code, the line var calculators = [subclass]() shows the error Invalid use of '()' to call a value of non-function type '[T.Type]'.
How can I return an array of ScientificCalculators from Calculator.createMultiple?
You were on the right track but you've made some mistakes.
First you need to return a array of T and not just a single element. So you need to change the return type from T to [T]:
class func createMultiple<T:Calculator>(num: Int) -> [T] {
Also you can just use T to initialize new instances of your subclass like that:
var calculators:[T] = [T]()
But the other parts are correct. So you final method would look like that:
extension Calculator {
class func createMultiple<T:Calculator>(num: Int) -> [T] {
let subclass: T.Type = T.self
var calculators = [T]()
for i in 0..<num {
calculators.append(subclass())
}
return calculators
}
}
Edit
If you are using Swift 1.2 you don't have to deal with subclass anymore and you will be able to use T instead like shown in Airspeeds answer.
calculators.append(T())
EDIT: this behaviour appears to have changed in the latest Swift 1.2 beta. You shouldn’t need to use T.self. T is the type you want to create. But if you are using 1.1, it appears not to work (even if T is the subtype, it creates the supertype), and using the metatype to create the type works around this problem. See end of answer for a 1.1 version.
You don’t need to mess with subclass: T.Type = T.self. Just use T – that itself is the type (or rather, a placeholder for whatever type is specified by the caller):
extension Calculator {
// you meant to return an array of T, right?
class func createMultiple<T: Calculator>(num: Int) -> [T] {
// declare an array of T
var calculators = [T]()
for i in 0..<num {
// create new T and append
calculators.append(T())
}
return calculators
}
}
btw, you can replace that for loop with map:
class func createMultiple<T: Calculator>(num: Int) -> [T] {
return map(0..<num) { _ in T() }
}
If you are still on Swift 1.1, you need to use T.self to work around a problem where the subtype is not properly created:
extension Calculator {
// only use this version if you need this to work in Swift 1.1:
class func createMultiple<T: Calculator>(num: Int) -> [T] {
let subclass: T.Type = T.self
return map(0..<num) { _ in subclass() }
}
}