Is there a way to make a generic type signature for a closure such that I can 
later call it generically? In particular my question is how to deal with an 
unknown number of arguments.

I have an object that I’d like to call a series of closures on an update, and 
I’d like other objects to be able to register closures that they’d like to be 
called with that first object.

Closures aren’t hashable, but I’d like to be able to also unregister a closure, 
so I wound up creating a custom type to handle this based on a dictionary:

//T is the closure signature such as Double->()
struct BlockCollection<T> : SequenceType {
    private var idx=0
    var blockDict:[Int:T]=[:]

    mutating func addBlock(b:T) -> Int {
        blockDict[idx]=b
        idx+=1
        return idx-1
    }

    mutating func dropBlock(k:Int) {
        blockDict.removeValueForKey(k)
    }

    func generate() -> AnyGenerator<T> {
        var dgen=blockDict.generate()
        return AnyGenerator {
            return dgen.next()?.1
        }
    }
}


This was some of the earliest Swift code I’d written, so looking back at it I 
can see room for improvement (including the type name), but it gets the job 
done.

This lets me use the collection in code like this:

Declare it:

private var stateCallbacks=BlockCollection<State<EngineType> -> ()> ()

Use it:

for b in stateCallbacks {
    b(newValue!)
}



So far, all’s good.  Now, I’d like to extend this idea to where I can ask the 
collection to run the for loop itself using syntax something like

stateCallbacks.runAllWith(newValue!)

I suspect that can be done if I know the blocks accept one argument and return 
one argument by using two type placeholders, say T for the argument and U for 
the return value. 

What I don’t seem able to do is make this generic across an unknown number of 
parameters.  The type I’m creating doesn’t care what the structure of the block 
is, it just wants to accept closures with a certain signature and then provide 
a mechanism to call them by exposing an API that depends on the closure 
signature.

For example, if I had a collection of closures with a signature such as 
`(Double, Double) -> ()`, I would want to be able to call the elements with 
`callbacks.runAllWith(d1,d2)`.

I don’t think there’s support for variadic generic parameters, so I can’t go 
down that road.  

Is there a way to do this without requiring the caller to bundle arguments into 
a tuple and then requiring a wrapper around each closure to unwrap a tuple of 
arguments and do a hand-crafted tuple splat?

Thanks—
 Greg




_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Reply via email to