[swift-users] How to store ref to any kind of function, and call with it argument list?

Slava Pestov spestov at apple.com
Sat Nov 4 00:31:20 CDT 2017


(Int) -> Int is not a subtype of (Any) -> Any, because a value of the latter type can be called with an argument type that is not an Int, for example a String:

let fn: (Int) -> Int = …
let fn2 = (Any) -> Any = fn // pretend this works

fn2(“hi”) // what does this do?

I think you’ll need to do something with generics where you wrap the original function value in a thunk that tests the argument type first, eg

func erase<T, U>(fn: (T) -> U) -> (Any) -> Any {
  return { any in fn(arg as! T) }
}

I haven’t thought this through properly since it’s late, but it might be a good starting point.

Slava

> On Nov 3, 2017, at 7:01 PM, C. Keith Ray <keithray at mac.com> wrote:
> 
> um... how can I cast functions taking one argument to a "generic function pointer" type?
> 
> typealias OneArgsFunction = (Any)->Any
> 
> func intToInt(_ i: Int) -> Int { return 4 }
> func floatToFloat(_ f: Float) -> Float { return 0.4 }
> 
> var function : OneArgsFunction = intToInt
> function = floatToFloat
> 
> error: f.playground:4:34: error: cannot convert value of type '(Int) -> Int' to specified type 'OneArgsFunction' (aka '(Any) -> Any')
> var function : OneArgsFunction = intToInt
>                                  ^~~~~~~~
> 
> error: f.playground:5:12: error: cannot assign value of type '(Float) -> Float' to type 'OneArgsFunction' (aka '(Any) -> Any')
> function = floatToFloat
>            ^~~~~~~~~~~~
> 
> 
> --
> C. Keith Ray
> Senior Software Engineer / Trainer / Agile Coach
> * http://www.thirdfoundationsw.com/keith_ray_resume_2014_long.pdf <http://www.thirdfoundationsw.com/keith_ray_resume_2014_long.pdf>
> 
> 
> 
>> On Nov 3, 2017, at 2:24 PM, Slava Pestov <spestov at apple.com <mailto:spestov at apple.com>> wrote:
>> 
>> Unfortunately we don’t have a way to invoke a function with a runtime argument list because that would require runtime code generation in the most general case.
>> 
>> I would hack around it by handling the common cases of no arguments, 1 argument, 2 arguments, etc up to some fixed number of arguments that you consider “enough”. Use a switch on the type of the function.
>> 
>> Slava
>> 
>>> On Nov 3, 2017, at 2:21 PM, C. Keith Ray via swift-users <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
>>> 
>>> In the code below, I'm trying to store a reference to a function with any number of arguments, with any return type. And I want to be able to invoke it. 
>>> 
>>> Help?
>>> 
>>> See the comments with "*******"
>>> 
>>> typealias Void = ()
>>> 
>>> func equalTypes(_ me: [Any.Type], _ other: [Any.Type]) -> Bool {
>>>     guard me.count == other.count else { return false }
>>>     
>>>     for i in 0 ..< me.count {
>>>         if me[i] != other[i] { return false }
>>>     }
>>>     return true
>>> }
>>> 
>>> struct Function {
>>>     var returnType: Any.Type
>>>     var argTypes: [Any.Type]
>>>     var function: Any // ******* any function *******
>>>     
>>>     func perform(_ args: [Any]) -> Any {
>>>         // ******* call function() with args, return result *******
>>>         return 0
>>>     }
>>>     
>>>     func isCompatible(_ other: Function) -> Bool {
>>>         return self.returnType == other.returnType &&
>>>             equalTypes(argTypes, other.argTypes)
>>>     }
>>> }
>>> 
>>> func vToV() {
>>>     print("vToV")
>>> }
>>> 
>>> func intToInt(_ i: Int) -> Int {
>>>     print("intToInt")
>>>     return 4
>>> }
>>> 
>>> let f = Function(returnType: Void.self,
>>>                  argTypes: [],
>>>                  function: vToV)
>>> let r = f.perform([])
>>> print(r)
>>> 
>>> let f2 = Function(returnType: Int.self,
>>>                  argTypes: [Int.self],
>>>                  function: intToInt)
>>> let r2 = f2.perform([12])
>>> print(r2)
>>> 
>>> assert(f.isCompatible(f))
>>> assert(!f.isCompatible(f2))
>>> 
>>> 
>>> --
>>> C. Keith Ray
>>> Senior Software Engineer / Trainer / Agile Coach
>>> * http://www.thirdfoundationsw.com/keith_ray_resume_2014_long.pdf <http://www.thirdfoundationsw.com/keith_ray_resume_2014_long.pdf>
>>> 
>>> 
>>> 
>>> _______________________________________________
>>> swift-users mailing list
>>> swift-users at swift.org <mailto:swift-users at swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-users <https://lists.swift.org/mailman/listinfo/swift-users>
>> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20171103/dc825b98/attachment.html>


More information about the swift-users mailing list