What is the best way to create a collection of blocks (or functions) that can have have items added and removed?
Items will be added from a variety of entry points (this is essentially a callback mechanism), and I'd like to be able to remove blocks from the collection from multiple points as well.
Edit: Originally this question focused on hashability in the hope that I could find a way of using Set. That earned me a duplicate tag because of the question of how to test blocks for equality. I don't think the answers to that question rule out a lightweight hashing method for blocks, but the answers to that question do rule out the use of the function pointer directly. I've changed the question to try to shake the tag.
var block={(x:Int) in print(x+1)}
I'm trying to make a collection of blocks that I can execute at a fairly high update rate (100's of Hz). I can make an Array of blocks, but then I can't remove one without first determining its index and the indices will change whenever one is removed, so storing the index isn't useful.
var ary:[Int->()]=[]
ary.append(block)
The next best option seems to be to make a Set of blocks, which allows me to remove a member as long as I've kept a copy of it around. Problem is, I can't make a set of objects that don't conform to Hashable.
var aset:Set<Int->()> //type 'Int -> ()' does not conform to protocol 'Hashable'
NSBlockOperation
is the object-wrapped version of a block. NSOperation
s, however are one-shot objects, so I would need to rebuild the NSBlockOperation
each time. This leads to two complications: having to recreate the NSOperation
after each invocation, and the significant overhead of creating NSOperation
s. Having to recreate the NSOperation
still means I need to keep a collection of blocks that I can add to and remove from-- so I'm back where I started...
Another option would be to use a Dictionary that's wrapped in some logic to generate unique keys for each block submitted. I think this will work, but seems like more logic than I should need.
struct BlockCollection : SequenceType {
private static var idx=0
var blockDict:[Int:Int->()]=[:]
mutating func addBlock(b:Int->()) -> Int {
blockDict[BlockCollection.idx]=b
BlockCollection.idx+=1
return BlockCollection.idx-1
}
mutating func dropBlock(k:Int) {
blockDict.removeValueForKey(k)
}
func generate() -> AnyGenerator<Int->()> {
var dgen=blockDict.generate()
return anyGenerator {
return dgen.next()?.1
}
}
}
Blocks are basically function pointers, right? Is there a way to access the pointer value and use it as the hash? Would that be a reasonable solution? [Edit: No, as indicated in the question on equality, the function pointer is not reliable after optimization.]