Variadic hash function

Would it make sense for hash to be variadic? In Python it is easy and cheap to create and pass a tuple to hash to hash multiple objects, but this is not possible in Mojo as Hashable objects are not necessarily Copyable and Movable. It also results in unnecessary copying. I propose making the following change to the builtin hash function.

from hashlib import Hasher
from hashlib._fnv1a import Fnv1a


fn hash[*Ts: Hashable, HasherType: Hasher = Fnv1a](*hashable: *Ts) -> UInt64:
    var hasher = HasherType()

    @parameter
    for i in range(len(VariadicList(Ts))):
        hasher.update(hashable[i])
    var value = hasher^.finish()
    return value


fn main():
    print(hash(1, 2.2, String("hello")))

I could see it being useful in some cases, but I think that you’re just as likely to want to add more stuff after the pack. I could see an argument for a “hash all of these things and give me the hasher” function.

However, right now hash is designed to match the signature of Python’s hash. For anything else, you should probably be using a hasher so you have better control over memory.

Thanks for a good answer!
The main use case I have is caching the hash value for large immutable structs. I made some changes based on your feedback, but I agree that this functionality does not need to be added to stdlib.

from hashlib import Hasher
from hashlib._fnv1a import Fnv1a


fn hash[*Ts: Hashable, HasherType: Hasher = Fnv1a](*hashable: *Ts, out hasher: HasherType):
    hasher = HasherType()

    @parameter
    for i in range(len(VariadicList(Ts))):
        hasher.update(hashable[i])
    


fn main():
    print(hash(1, 2.2, String("hello")).finish())