Ways to infer type to generic function - swift

How can I infer a type to a generic function other than like this:
let a: MyType = genericFunction()
or these casts:
let a = MyType(genericFunction())
let a = genericFunction() as MyType
A conditional cast doesn’t infer the type:
let a = genericFunction() as? MyType
What else does?
UPDATE:
As Victor Pro assumed the function should return a generic type. It could look like:
func genericFunction<T>() -> T {
}

I assume your genericFunction() has a generic return type. Then, another way to infer the type is to pass it as an argument to the function: func genericFunction<T>(returnType: T.Type) -> T {...}. You can call it now via e.g. let val = genericFunction(String.self), whereby val is of type String.

Related

Generic Functions and Protocols in Swift 3.2 failing to infer type

Given the following .
func doSomething<T: JSONDecodable>() -> [T] { return [] }
and a concrete type of Animal: JSONDecodable I'm trying to invoke the doSomething method without specifying the type of Animal.
The following works: let result: [Animal] = doSomething()
The following examples do not:
let result: [JSONDecodable] = doSomething() // Cannot convert value of type '_' to closure result 'JSONDecodables'
Storing out the type:
let savedType = Animal.Type
let result: [savedType] = doSomething() // Use of undeclared type savedType
Any suggestions to how to hint the compiler without specifying the concrete type?

Pass class as param into function for comparison in swift?

I want to write something like this:
func someFunc<T, U>(t1: T.Type, t2: U.Type) {
let k = someArray.first {$0 is t1}
...
}
It writes:
Use of undeclared type 't1'
Objective-C has Class and has class comparison but it seems swift hasn't it properly implemented.
Since this is a generic function you can use the generic type T instead of t1.
let k = someArray.first {$0 is T}

Swift Cast to Generic Type with Constraint

I am using Swift 3 with constrained generics (i.e. a where clause). I have a problem when I am trying to do generic type casting. Here is a simplified example of the problem:
func jsonToObj<T:DomainResource>(jsonStr: String) -> [T:DomainResource] {
let json = JSON(parseJSON: jsonStr).dictionaryObject
let bundle = SMART.Bundle(json: json)
let result = bundle.entry?.map() {
return $0.resource as! T
}
return result!
}
My problem is when I return from the method, the compiler complains its cannot convert type [T] to type [T:DomainResource]. If I remove the DomainResource constraint from the generic, it compiles and runs just fine.
That's not what I want, so, I tried this:
let result = bundle.entry?.map() {
return $0.resource as! T:DomainResource
}
Swift doesn't seem to know what that means. Any idea on how to work around this problem? I'd like to not just cast them all to DomainResource objects, if possible.
You wrote this function signature:
func jsonToObj<T:DomainResource>(jsonStr: String) -> [T:DomainResource]
This says that the jsonToObj(jsonStr:) method returns a dictionary whose keys are of type T and whose values are of type DomainResource. It looks like you just want to write this function signature:
func jsonToObj<T:DomainResource>(jsonStr: String) -> [T]

Return any type from a function in Swift

I am attempting to create a function that can return any type. I do not want it to return an object of type Any, but of other types, i.e. String, Bool, Int, etc. You get the idea.
You can easily do this using generics in this fashion:
func example<T>(_ arg: T) -> T {
// Stuff here
}
But is it possible to do it without passing in any arguments of the same type? Here is what I am thinking of:
func example<T>() -> T {
// Stuff here
}
When I try to do this, everything works until I call the function, then I get this error:
generic parameter 'T' could not be inferred
is it possible to do it without passing in any arguments of the same type?
The answer is yes, but there needs to be a way for the compiler to infer the correct version of the generic function. If it knows what it is assigning the result to, it will work. So for instance, you could explicitly type a let or var declaration. The below works in a playground on Swift 3.
protocol Fooable
{
init()
}
extension Int: Fooable {}
extension String: Fooable {}
func foo<T: Fooable>() -> T
{
return T()
}
let x: String = foo() // x is assigned the empty string
let y: Int = foo() // y is assigned 0

How do I call a generic Swift function when none of the arguments provides the generic type?

The following compiles in the Swift REPL:
var m: [String:AnyObject] = [:]
func f<T: AnyObject>(s: String) {
m[s] = T.self
}
However, if I naively try to invoke f(), thus:
let s: String = "foo"
class Foo {}
f<Foo>(s)
I get this error:
repl.swift:7:1: error: cannot explicitly specialize a generic function
f<Foo>(s)
^
repl.swift:7:2: note: while parsing this '<' as a type parameter bracket
f<Foo>(s)
^
If I try it without "explicitly specializing"...
f(s)
Swift decides I'm trying to do something even weirder, and I get:
repl.swift:7:1: error: cannot convert the expression's type 'String' to type '()'
f(s)
^~~~
Meanwhile, however, if I define a new function g() as follows:
func g<T: AnyObject>(s: String, t: T) {
m[s] = T.self
}
and pass in a dummy Foo instance:
g(s, Foo())
it works fine:
> m
$R0: [String : AnyObject] = {
[0] = {
key = "foo"
value = {
instance_type = {}
}
}
}
So is there a reason Swift lets me define f() in the first place? And once defined, is there any way to invoke it?
ETA: I'm aware it's also possible to define a function h<T: AnyObject>(s: String, t: T.Type) that takes the type explicitly. It's the fact that Swift allows me to define the implicit version that I find questionable.
Differently from other languages, you cannot explicitly specify the generic type with a syntax like this:
f<Foo>(s)
instead the actual type is inferred via a parameter or the return type. In your case you are not providing a way for type inference to figure out what T is. And sadly I'm not aware of any way to use that function.
My suggestion is to explicitly pass the type of T:
func f<T: AnyObject>(s: String, type: T.Type) {
m[s] = type
}
...
f(s, Foo.self)