`AnyFunc` base protocol for all blocks and methods

I'm not a frequent visitor so apologies if this has been discussed before. I did try to find similar proposals with no success so maybe this could be worth discussing here.

I recently implemented a small generalized Publish/Subscribe library for personal use, which ended up being an exercise in functional programming. One thing I missed was better ways to manipulate methods/blocks in a generic way.

Giving it some further thought, I figured something like the following would work well to solve many of the limitations I had to work under (all identifiers subject to change):

protocol AnyFunc {
    associatedtype Result
    associatedtype Params

    func call(withParams params: Params) -> Result
}

The idea is that all blocks/functions would inherently implement this protocol not unlike, say, AnyObject for class instances.

This would allow a developer to write generic logic wrt function manipulation and calling irrespective to how many parameters there are (Params would be a tuple for more than one, same as Result) and more easily set up generic logic like where Method.Result == Void

I'm not sure if this would be workable with inout parameters, but I don't think it would have cause any new issues that don't exist already with those.

1 Like

Could you give an example of how this would have been useful for you?

1 Like

I wanted to be able to do Publish/Subscribe with an arbitrary number of parameters for the callbacks, and this was a decent way to go about it, as an example (a very simplified version of what I ended up building, which is limited to a single parameter for subscription updates):

struct Publisher<SubscriptionFunc> where SubscriptionFunc: AnyFunc, SubscriptionFunc.Result == Void {

    func subscribe(withSubscriptionFunc subscriptionFunc: SubscriptionFunc) { ... }

    var subscribers: [SubscriptionFunc]

    func updateSubscribers(withUpdate update: SubscriptionFunc.Params) {
        for subscriptionFunc in subscribers {
            subscriptionFunc.call(withParams: update)
        }
    }
}