Is it possible to assign a generic function to a variable?
You can let Swift infer the specialization of function2
by the explicit type annotation of f2
:
let f2: (Int) -> Int = function2
Alternatively, use an intermediate specializer function which supplies the explicit type annotation
func specialize1Dmap<T>(_ f: @escaping (T) -> T, as _: T.Type) -> (T) -> T { return f }
let f2int = specialize1Dmap(function2, as: Int.self)
let f2str = specialize1Dmap(function2, as: String.self)
Assign to generic function parameter in TypeScript
I am not quite sure what you are trying to achieve here but moving U
to the front will fix this problem:
function foo<U>(a: number, f: (a: number) => U) {
return f(a)
}
function bar(a: number) : number {
return 2*a
}
foo(8, bar);
If you want to introduce generic types in a function declaration you should put them right after the function name. When the function is called TypeScript will then try to infer the correct types.
Assigning a Function with Generic Parameter to a Variable
var speakFuction: (speaker: ThingSayer) -> Void = aLoudspeaker.saySomething
You'll need to explicit the type of your function when declaring the variable to help the compiler.
Function with generic type as member variable
In Java (and JVM) values are not polymorphic, methods are.
So correct is to define it with a method
<T> Function<Class<T>, T> fun();
Polymorphic values in Java
Regarding EDIT.
Now, I want to hand a pointer to that function to class
B
like this:public class B {
<T> Function<Class<T>, T> fun;
public <T> T get(Class<T> clazz) {
return fun.apply(clazz);
}
}
Once again, a value (including a field) can't be polymorphic, method can.
So you can make
fun
a methodpublic abstract class B {
abstract <T> Function<Class<T>, T> fun();
public <T> T get(Class<T> clazz) {
return this.<T>fun().apply(clazz);
}
}You can't write setter like
setFun
. Its signature should be something likepublic void setFun(<T> Function<Class<T>, T> fun); // pseudocode
rather than
public <T> void setFun(Function<Class<T>, T> fun);
<T> Function<Class<T>, T>
is called rank-N type and it's absent in JavaWhat is the purpose of Rank2Types?
https://wiki.haskell.org/Rank-N_types
Alternatively, you can wrap polymorphic
fun
with a class (interface)public interface PolyFunction {
<T> T apply(Class<T> clazz);
}
public class B {
PolyFunction fun;
public void setFun(PolyFunction fun) {
this.fun = fun;
}
public <T> T get(Class<T> clazz) {
return fun.apply(clazz);
}
}PolyFunction
looks like yourA
so maybe you wantpublic class B {
A a;
public void setA(A a) {
this.a = a;
}
public <T> T get(Class<T> clazz) {
return a.get(clazz);
}
}
Swift: Assign an instance of a generic type to a class variable?
Break down the create method signature and the Batch1 type
public func create<Request: JSONRPCKit.Request>(_ request: Request) -> Batch1<Request>
public struct Batch1<Request: JSONRPCKit.Request>: Batch {
public typealias Responses = Request.Response
public typealias Results = Result<Request.Response, JSONRPCError>
}
create
is a generic function that takes a single parameter of any type. The constraint <Request: JSONRPCKit.Request>
specifies that the parameter's type must conform to the protocol JSONRPCKit.Request
.
Batch1
is a generic struct that needs to define two internal types, both of which are associated with some arbitrary type. Again, <Request: JSONRPCKit.Request>
specifies that that arbitrary type must conform to the protocol JSONRPCKit.Request
.
The return type Batch1<Request>
ties these two generics together, saying that the type used for the returned Batch1
struct will match the type of the request
parameter.
When you call the create method, you must fill in the generic type with a concrete type, as in the example
let batch = batchFactory.create(Subtract(minuend: 42, subtrahend: 23))
Now the compiler can go through all of the definitions and create concrete implementations for that type:
public func create(_ request: Subtract) -> Batch1<Subtract>
public struct Batch1<Subtract>: Batch {
public typealias Responses = Int
public typealias Results = Result<Int, JSONRPCError>
}
This uses the fact that Subtract
defines typealias Response = Int
. Note that nothing is generic anymore; these are all concrete types. You would have no issue with trying to store a property of type Batch1<Subtract>
.
This is why you can't easily store the batch in a property: Swift has no idea what types to put in it!
One way around this is to instead store a closure, this can wrap the generic batch such that the class doesn't have to know about it
// closure property
var responseProcessor: ((Any) -> Void)?
func createBatch<R: JSONRPCKit.Request>(request: R, processor: @escaping (R.Response) -> Void) {
let batch = batchFactory.create(request)
self.responseProcessor = { responseObject in
let response = try! batch.responses(from: responseObject)
processor(response)
}
}
// somewhere else when you get the responseObject
responseProcessor?(responseObject)
This method takes a specific closure that matches the generic type and wraps it in a closure that is no longer dependent on the generic. This way every batch can share the same closure property.
Unable to assign function to type with generic parameter
As mentioned by kaya3, you are trying to assign a function that take a specific type, string[]
, to a function that takes generic types . What you may do instead, is, define a type with the generic signature. And then create a function that takes is one specific instance of that generic signature. Something like this:
type MyType<T> = (v: T) => string;
const s: MyType<string[]> = (v: string[]) => v[0] || 'x' ;
If you have just one type, this would be sufficient:
const s = (v: string[]) => v[0] || 'x' ;
How to define a generic function type in Typescript; two similar ways?
This:type ConcatX<T> = (a: T, b: T) => T;
type ConcatX<T> = (a: T, b: T) => T;
Is a generic type alias, which contains a function that uses the generic parameter. The generic parameter this function uses is locked in once the type is resolved. That can be handy when some type needs to set the type of your function.
For instance here:
const sum: ConcatX<number> = (a, b) => a + b;
This says that, externally to this function, you declare that the arguments of this function are numbers.
Note that this is not really part of the function type at all. This approach isn't fundamentally different than something like:
type ContatX<T> = { sum(a: T, b: T): T, someValue: T }
The point being that the T
is set outside the function entirely, and the function just picks that up to use.
This:type ConcatY = <T>(a: T, b: T) => T;
type ConcatY = <T>(a: T, b: T) => T;
Is a generic function. The generic parameter is set when the function is called, and can be different each time it's called. And that parameter may be inferred from the type of the arguments a
and b
.
You cannot lock down T
ahead of time here because T
is decided when the function is called and no sooner.
Which means there is no subtype of ConcatY
that only takes numbers. To type guard against bad usage here you would instead check the return type:
const resultStr: string = sum(1,2) // error: cannot assign number to string
const resultNum: num = sum('a','b') // error: cannot assign string to number
In both cases the function call is completely valid, but the result is not what the type system is expecting, so you get an error.
If you want a specific subtype of concat where the arguments must be numbers, then you want the generic type ConcatX
.
But if your function could take lots of different arguments, and the return type depends on the type of those arguments, and you don't know exactly what types it will be called with ahead of time, then you want the generic function ContactY
.
Which all means that if you want to:
"to indicate that a function takes one of these with specific argument types"
Then you need to use ContactX
with a generic parameter to create a function type with the T
locked to whatever you want.
Related Topics
Tableview Image Content Selection Color
Bridgetoobjectivec Not Available on Swift Beta 5
Why Does Cabasicanimation Try to Initialize Another Instance of My Custom Calayer
How to Check If a Variable Is Nil
How to Retrieve The Name of Participants in Msconversation
How to Map Over The Values of Zip2
Table View Cells Changing Colors When Scrolling Swift
Sbdata Is Wrong When Sbvalue Comes from a Swift Dictionary
Arkit - Raycasting Using a World Ray Instead of a Screen Point
Swift Lose Precision in Decimal Formatting
"'Init' Is Deprecated" Warning After Swift4 Convert
How to Get Wkwebview to Work in Swift and for an Macos App
Nil Cannot Be Assigned to Type Avcapturedeviceinput
Swift Navigation Bar Item Not Calling Action
Ckasset in Server Record Contains No Fileurl, Cannot Even Check for Nil