Thanks, that's working for me, though I have to specify the return type explicitly to avoid compile error.
typealias TwoArgsFunction = (Any,Any)->Any func intToInt(_ i: Int, d: Double) -> Int { print("intToInt \(i) \(d)") return 4 } func typeEraseTwo<Arg1T,Arg2T,R>(r: R.Type, fn: @escaping (Arg1T,Arg2T)->R) -> TwoArgsFunction { return { guard let arg1 = $0 as? Arg1T else { fatalError("\(Arg1T.self) wrong type \(type(of:$0)) \($0) ") } guard let arg2 = $1 as? Arg2T else { fatalError("\(Arg2T.self) wrong type \(type(of:$1)) \($1) ") } return fn(arg1, arg2) } } var function : TwoArgsFunction = typeEraseTwo(r: Int.self, fn: intToInt) let r = function(12, 5.5) print(r) // prints "intToInt 12 5.5" and "4" ...and Xcode just crashed while I was typing in a playground. -- C. Keith Ray Senior Software Engineer / Trainer / Agile Coach * http://www.thirdfoundationsw.com/keith_ray_resume_2014_long.pdf > On Nov 3, 2017, at 10:31 PM, Slava Pestov <spes...@apple.com> wrote: > > (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 <keith...@mac.com >> <mailto:keith...@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 <spes...@apple.com >>> <mailto:spes...@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@swift.org <mailto:swift-users@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@swift.org <mailto:swift-users@swift.org> >>>> https://lists.swift.org/mailman/listinfo/swift-users >>>> <https://lists.swift.org/mailman/listinfo/swift-users> >>> >> >
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users