Swift Passing a Generic from a Function - swift

I have the following function :
Amplify.API.query(request: .get(
self.getObjectForOCObject(ocObject: ocObject)!, byId: id)) { event in
The definition of the get function is :
public static func get<M: Model>(_ modelType: M.Type,
byId id: String) -> GraphQLRequest<M?> {
My getObjectForObject is as follows :
func getObjectForOCObject <M: Model>(ocObject:NSObject) -> M.Type?
{
if type (of:ocObject) == type(of: OCAccount.self)
{
return Account.self as? M.Type
}
return nil;
}
But I'm getting a"Generic Parameter 'M' could not be inferred. I get that the compiler cannot determine what type of object this is. However I don't know how to fix this. I need my getObjectForOCObject function to return what it is expecting. Essentially I'm trying to return the type of object based on the type of another object.
Normally this call is done this way and it works...
Amplify.API.query(request: .get(Account.self, byId: id)) { event in
I'm trying to avoid having to create a number of functions to handle each different Model in my code as that is being handled in higher up in the call hierarchy. Which is why I'm trying to do this. Otherwise I'm going to have to write essentially the same code in multiple places. In Objective C one can use the super class to pass objects around but the inheriting class still comes along with it. But with Swift being dynamically typed, I'm running into this issue.
The closest I've gotten is this... Changing the getObjectForOCObject return to Model.Type? as so :
func getObjectForOCObject (ocObject:NSObject) -> Model.Type?
{
if type (of:ocObject) == type(of: OCAccount.self)
{
return Account.self
}
return nil;
}
Then I get a Cannot convert value of type 'Model.Type?' to expected argument type 'M.Type' But aren't these essentially the same thing based on the .get function above?
Hoping for some insight here. Also, FYI, I'm pretty terrible with Swift so I'm certain I'm definitely doing some bad things in Swift here. I'm an expert with ObjC. I'm just trying to create a bridge between the two for this Swift library I'm using.

Related

Extension with a generic where clause is not beeing called

The following code works just as expected:
protocol Storeable {
associatedtype Value
func create(value: Value)
}
struct DefaultStore<V>: Storeable {
typealias Value = V
func create(value: V) {
print("base impl. is called with value type: \(String(describing: V.self))")
}
}
class Event {
var title: String = ""
init(title: String) {
self.title = title
}
}
extension DefaultStore where Value: Event {
func create(value: V) {
print("event impl. is called with event: \(value.title)")
}
}
DefaultStore().create(value: Event(title: "Dance Party"))
// prints "event impl. is called with event: Dance Party"
DefaultStore().create(value: "a string object")
// prints "base impl. is called with value of type: String"
Basically I call a function on the generic class DefaultStore and the compiler calls the correct implementation depending on the underlying type.
Now I have a scenario where I want the exact same thing except, that it is wrapped in another object called Wrapper:
struct Wrapper<StoreType: Storeable,ValueType> where StoreType.Value == ValueType {
let store: StoreType
func create(value: ValueType) {
store.create(value: value)
}
}
let defaultStore = DefaultStore<Event>()
let wrapper = Wrapper(store: defaultStore)
wrapper.create(value: Event(title: "Düsseldorfer Symphoniker"))
// prints: "base impl. is called with value of type: Event"
Here I expect that the extension for Event is called but instead the base implementation is called. Anyone any idea what I am doing wrong?
--
Update:
#matt was guessing that there might be a compile time issue: "without the wrapper when you say DefaultStore().create... the Event info can be read all the way back to the DefaultStore generic parameterized type. But in your wrapper the DefaultStore is created first so it is the general type and that's all it is."
I believe that is not the case because you can also create the DefaultsStore first and it's still working without the Wrapper. Also the compiler warns me if the types don't match.
Nothing to do with "wrappers".
You seem to think that a where extension on a generic struct is a kind of substitute for some sort of dynamic dispatch, i.e. we're going to wait until runtime, look to see what kind of object the parameter to create really is, and dispatch accordingly. That's not how it works. Everything has to be resolved at compile time. At compile time, what we know is that you are not calling create with an Event — you are calling it with a ValueType. So it passes into the create with generic V.
So, for example:
struct Wrapper {
let store: DefaultStore<Event>
func create(value: Event) {
store.create(value: value)
}
}
That works the way you have in mind because we are exposing the fact that this is an Event as far as the DefaultStore is concerned at the point of calling create.
That's just a guess at what your confusion is.
Another possibility is you might imagine that the generic resolution of ValueType somehow "leaks" up to the resolution of V, but that's not true either.
Yet another possibility is you might suppose that a DefaultStore<Event> is a subtype of DefaultStore<Storable> or similar, as if there were dynamic dispatch for parameterized types, but that is exactly what is not the case. Everything has to be known completely at compile time at the call site.

Swift: casting un-constrained generic type to generic type that confirms to Decodable

Situation
I have a two generic classes which will fetch data either from api and database, lets say APIDataSource<I, O> and DBDataSource<I, O> respectively
I will inject any of two class in view-model when creating it and view-model will use that class to fetch data it needed. I want view-model to work exactly same with both class. So I don't want different generic constraints for the classes
// sudo code
ViewModel(APIDataSource <InputModel, ResponseModel>(...))
// I want to change the datasource in future like
ViewModel(DBDataSource <InputModel, ResponseModel>(...))
To fetch data from api ResponseModel need to confirms to "Decodable" because I want to create that object from JSON. To fetch data from realm database it need to inherit from Object
Inside ViewModel I want to get response like
// sudo code
self.dataSource.request("param1", "param2")
If developer tries to fetch api data from database or vice-versa it will check for correct type and throws proper error.
Stripped out version of code for playground
Following is stripped out version of code which shows what I want to achieve or where I am stuck (casting un-constrained generic type to generic type that confirms to Decodable)
import Foundation
// Just to test functions below
class DummyModel: Decodable {
}
// Stripped out version of function which will convert json to object of type T
func decode<T:Decodable>(_ type: T.Type){
print(type)
}
// This doesn't give compilation error
// Ignore the inp
func testDecode<T:Decodable> (_ inp: T) {
decode(T.self)
}
// This gives compilation error
// Ignore the inp
func testDecode2<T>(_ inp: T){
if(T.self is Decodable){
// ??????????
// How can we cast T at runtime after checking T confirms to Decodable??
decode(T.self as! Decodable.Type)
}
}
testDecode(DummyModel())
Any help or explanation that this could not work would be appreciated. Thanks in advance :)
As #matt suggests, moving my various comments over to an answer in the form "your problem has no good solution and you need to redesign your problem."
What you're trying to do is at best fragile, and at worst impossible. Matt's approach is a good solution when you're trying to improve performance, but it breaks in surprising ways if it impacts behavior. For example:
protocol P {}
func doSomething<T>(x: T) -> String {
if x is P {
return "\(x) simple, but it's really P"
}
return "\(x) simple"
}
func doSomething<T: P>(x: T) -> String {
return "\(x) is P"
}
struct S: P {}
doSomething(x: S()) // S() is P
So that works just like we expect. But we can lose the type information this way:
func wrapper<T>(x: T) -> String {
return doSomething(x: x)
}
wrapper(x: S()) // S() simple, but it's really P!
So you can't solve this with generics.
Going back to your approach, which at least has the possibility of being robust, it's still not going to work. Swift's type system just doesn't have a way to express what you're trying to say. But I don't think you should be trying to say this anyway.
In the method that fetch data I will check type of generic type and if it confirms to "Decodable" protocol I will use it to fetch data from api else from database.
If fetching from the API vs the database represents different semantics (rather than just a performance improvement), this is very dangerous even if you could get it to work. Any part of the program can attach Decodable to any type. It can even be done in a separate module. Adding protocol conformance should never change the semantics (outwardly visible behaviors) of the program, only the performance or capabilities.
I have a generic class which will fetch data either from api or database
Perfect. If you already have a class, class inheritance makes a lot of sense here. I might build it like:
class Model {
required init(identifier: String) {}
}
class DatabaseModel {
required init(fromDatabaseWithIdentifier: String) {}
convenience init(identifier: String) { self.init(fromDatabaseWithIdentifier: identifier )}
}
class APIModel {
required init(fromAPIWithIdentifier: String) {}
convenience init(identifier: String) { self.init(fromAPIWithIdentifier: identifier )}
}
class SomeModel: DatabaseModel {
required init(fromDatabaseWithIdentifier identifier: String) {
super.init(fromDatabaseWithIdentifier: identifier)
}
}
Depending on your exact needs, you might rearrange this (and a protocol might also be workable here). But the key point is that the model knows how to fetch itself. That makes it easy to use Decodable inside the class (since it can easily use type(of: self) as the parameter).
Your needs may be different, and if you'll describe them a bit better maybe we'll come to a better solution. But it should not be based on whether something merely conforms to a protocol. In most cases that will be impossible, and if you get it working it will be fragile.
What you'd really like to do here is have two versions of testDecode, one for when T conforms to Decodable, the other for when it doesn't. You would thus overload the function testDecode so that the right one is called depending on the type of T.
Unfortunately, you can't do that, because you can't do a function overload that depends on the resolution of a generic type. But you can work around this by boxing the function inside a generic type, because you can extend the type conditionally.
Thus, just to show the architecture:
protocol P{}
struct Box<T> {
func f() {
print("it doesn't conform to P")
}
}
extension Box where T : P {
func f() {
print("it conforms to P")
}
}
struct S1:P {}
struct S2 {}
let b1 = Box<S1>()
b1.f() // "it conforms to P"
let b2 = Box<S2>()
b2.f() // "it doesn't conform to P"
This proves that the right version of f is being called, depending on whether the type that resolves the generic conforms to the protocol or not.

Extension Error Swift 3 JSON

I'm trying to migrate my app to Swift 3 but I have troubles.
The code section that struggles me is:
extension JSON: Swift.BooleanType {
//Optional bool
public var bool: Bool? {
get {
switch self.type {
case .bool:
return self.object.boolValue
default:
return nil
}
}
set {
if newValue != nil {
self.object = NSNumber(value: newValue! as Bool)
} else {
self.object = NSNull()
}
}
}
On first line is where xCode throws an error:
extension JSON: Swift.BooleanType {
The error says: Inheritance from non-protocol type 'BooleanType' (aka 'Bool')
Does anybody know what's happening there?
Simplest solution is here,
Bad : extension JSON: Swift.BooleanType {
Good : extension JSON: {
Reason : Admittedly, I am using this to modify SwiftyJSON which is a framework for processing JSON data. In doing some research it seems that they didn't allow BooleanType to allow for inheritance. The suggested means of dealing with this is simply to remove the type.
link is given : https://forums.developer.apple.com/thread/53405
Protocols are Swift's equivalent of Java interfaces. If you've never worked with interfaces before, they're classes absent of any concrete implementation. They exist to describe the skeleton of a class (the attribute and method names it should have) without actually implementing them so that other classes that inherit from the interface can flesh them out later. In Swift they're particularly useful for implementing the Delegate pattern.
Boolean is not a protocol. It is very much a living, breathing concrete Type with an existing implementation. To do what you want to do you either need to override the existing get/set method for Boolean type or create your own Boolean type as described in the official Apple Swift Blog.

Swift: Overriding Self-requirement is allowed, but causes runtime error. Why?

I just started to learn Swift (v. 2.x) because I'm curious how the new features play out, especially the protocols with Self-requirements.
The following example is going to compile just fine, but causes arbitrary runtime effects to happen:
// The protocol with Self requirement
protocol Narcissistic {
func getFriend() -> Self
}
// Base class that adopts the protocol
class Mario : Narcissistic {
func getFriend() -> Self {
print("Mario.getFriend()")
return self;
}
}
// Intermediate class that eliminates the
// Self requirement by specifying an explicit type
// (Why does the compiler allow this?)
class SuperMario : Mario {
override func getFriend() -> SuperMario {
print("SuperMario.getFriend()")
return SuperMario();
}
}
// Most specific class that defines a field whose
// (polymorphic) access will cause the world to explode
class FireFlowerMario : SuperMario {
let fireballCount = 42
func throwFireballs() {
print("Throwing " + String(fireballCount) + " fireballs!")
}
}
// Global generic function restricted to the protocol
func queryFriend<T : Narcissistic>(narcissistic: T) -> T {
return narcissistic.getFriend()
}
// Sample client code
// Instantiate the most specific class
let m = FireFlowerMario()
// The call to the generic function is verified to return
// the same type that went in -- 'FireFlowerMario' in this case.
// But in reality, the method returns a 'SuperMario' and the
// call to 'throwFireballs' will cause arbitrary
// things to happen at runtime.
queryFriend(m).throwFireballs()
You can see the example in action on the IBM Swift Sandbox here.
In my browser, the output is as follows:
SuperMario.getFriend()
Throwing 32 fireballs!
(instead of 42! Or rather, 'instead of a runtime exception', as this method is not even defined on the object it is called on.)
Is this a proof that Swift is currently not type-safe?
EDIT #1:
Unpredictable behavior like this has to be unacceptable.
The true question is, what exact meaning the keyword Self (capital first letter) has.
I couldn't find anything online, but there are at least these two possibilities:
Self is simply a syntactic shortcut for the full class name it appears in, and it could be substituted with the latter without any change in meaning. But then, it cannot have the same meaning as when it appears inside a protocol definition.
Self is a sort of generic/associated type (in both protocols and classes) that gets re-instantiated in deriving/adopting classes. If that is the case, the compiler should have refused the override of getFriend in SuperMario.
Maybe the true definition is neither of those. Would be great if someone with more experience with the language could shed some light on the topic.
Yes, there seems to be a contradiction. The Self keyword, when used as a return type, apparently means 'self as an instance of Self'. For example, given this protocol
protocol ReturnsReceived {
/// Returns other.
func doReturn(other: Self) -> Self
}
we can't implement it as follows
class Return: ReturnsReceived {
func doReturn(other: Return) -> Self {
return other // Error
}
}
because we get a compiler error ("Cannot convert return expression of type 'Return' to return type 'Self'"), which disappears if we violate doReturn()'s contract and return self instead of other. And we can't write
class Return: ReturnsReceived {
func doReturn(other: Return) -> Return { // Error
return other
}
}
because this is only allowed in a final class, even if Swift supports covariant return types. (The following actually compiles.)
final class Return: ReturnsReceived {
func doReturn(other: Return) -> Return {
return other
}
}
On the other hand, as you pointed out, a subclass of Return can 'override' the Self requirement and merrily honor the contract of ReturnsReceived, as if Self were a simple placeholder for the conforming class' name.
class SubReturn: Return {
override func doReturn(other: Return) -> SubReturn {
// Of course this crashes if other is not a
// SubReturn instance, but let's ignore this
// problem for now.
return other as! SubReturn
}
}
I could be wrong, but I think that:
if Self as a return type really means 'self as an instance of
Self', the compiler should not accept this kind of Self requirement
overriding, because it makes it possible to return instances which
are not self; otherwise,
if Self as a return type must be simply a placeholder with no further implications, then in our example the compiler should already allow overriding the Self requirement in the Return class.
That said, and here any choice about the precise semantics of Self is not bound to change things, your code illustrates one of those cases where the compiler can easily be fooled, and the best it can do is generate code to defer checks to run-time. In this case, the checks that should be delegated to the runtime have to do with casting, and in my opinion one interesting aspect revealed by your examples is that at a particular spot Swift seems not to delegate anything, hence the inevitable crash is more dramatic than it ought to be.
Swift is able to check casts at run-time. Let's consider the following code.
let sm = SuperMario()
let ffm = sm as! FireFlowerMario
ffm.throwFireballs()
Here we create a SuperMario and downcast it to FireFlowerMario. These two classes are not unrelated, and we are assuring the compiler (as!) that we know what we are doing, so the compiler leaves it as it is and compiles the second and third lines without a hitch. However, the program fails at run-time, complaining that it
Could not cast value of type
'SomeModule.SuperMario' (0x...) to
'SomeModule.FireFlowerMario' (0x...).
when trying the cast in the second line. This is not wrong or surprising behaviour. Java, for example, would do exactly the same: compile the code, and fail at run-time with a ClassCastException. The important thing is that the application reliably crashes at run-time.
Your code is a more elaborate way to fool the compiler, but it boils down to the same problem: there is a SuperMario instead of a FireFlowerMario. The difference is that in your case we don't get a gentle "could not cast" message but, in a real Xcode project, an abrupt and terrific error when calling throwFireballs().
In the same situation, Java fails (at run-time) with the same error we saw above (a ClassCastException), which means it attempts a cast (to FireFlowerMario) before calling throwFireballs() on the object returned by queryFriend(). The presence of an explicit checkcast instruction in the bytecode easily confirms this.
Swift on the contrary, as far as I can see at the moment, does not try any cast before the call (no casting routine is called in the compiled code), so a horrible, uncaught error is the only possible outcome. If, instead, your code produced a run-time "could not cast" error message, or something as gracious as that, I would be completely satisfied with the behaviour of the language.
The issue here seems to be a violation in contract:
You define getFriend() to return an instance of receiver (Self). The problem here is that SuperMario does not return self but it returns a new instance of type SuperMario.
Now, when FireFlowerMario inherits that method the contract says that the method should return a FireFlowerMario but instead, the inherited method returns a SuperMario! This instance is then treated as if it were a FireFlowerMario, specifically: Swift tries to access the instance variable fireballCount which does not exist on SuperMario and you get garbage instead.
You can fix it like this:
class SuperMario : Mario {
required override init() {
super.init()
}
override func getFriend() -> SuperMario {
print("SuperMario.getFriend()")
// Dynamically create new instance of the same type as the receiver.
let myClass = self.dynamicType
return myClass.init()
}
}
Why does the compiler allow it? It has a hard time catching something like this, I guess. For SuperMario, the contract is still valid: the method getFriend does return an instance of the same class. The contract breaks when you create the subclass FireFlowerMario: should the compiler notice that a superclass might violate the contract? This would be an expensive check and probably more suited for a static analyzer, IMHO (Also, what happens if the compiler doesn't have access to SuperMario's source? What happens if that class is from a library?)
So it's actually SuperMario's duty to ensure that the contract is still valid when subclassing.

Bottom Type in Swift

I'm wondering if there is bottom type in the Swift language.
To weed out any confusion beforehand, unit type is a different kind than bottom type as we have it as Void or () in swift. Also Any is top type.
What I've found to be the closest, surprisingly, is #noreturn attribute in the form of fatalError() in that we can mostly pass this function to conform to most given arbitrary type.
But, of course, this is incomplete and thus a bad substitute for a true bottom type as, for example, Nothing in Scala, undefined in Haskell or even null in Java.
So, is there a bottom type in Swift language?
Turns out there is no Bottom Type in swift, but we can mock its general behavior through few hacks with #noreturn attribute and generics as explained in this talk.
func undefined<A>(_ message: String = "") -> A {
fatalError("Not Implemented: \(message)")
}
Then we can use it to mark yet-implemented parts of our code to pass compiler errors:
func someComplexFunction<U: User>(u: U) -> U {
return undefined("Do this after creating user")
}
Or to prove some invariances in our code:
let array = ["hello", "world"]
let hello: String = array.first ?? undefined("This is impossible!")
see Never
Basically, you can just do
func foo() -> Never {
// you can't return
}