Cache FunctionSpace by mesh, element, dim, rank

A FunctionSpace on a given mesh and element is unique. We therefore
cache it with the mesh, element, dim and rank as the cache key.