Speed Efficiency

(person-age dave) ultimately expands to (aref dave 1) which is an array access. Array access and hash access should both be O(1) operations. However, the k for hash access will be much greater.

First of all, you need to call the hash function. Even if that is just mod [size of hash] that will probably more than halve the speed. And then you have collision handling on top of that.

Space Efficiency

A default hash table starts with 65 slots.

(make-hash-table) ;; --> #<hash-table 'eql nil 0/65 0x298a880>

That is quite a lot of overhead for an object with just a few fields. You can select a different initial size, but as you might expact, a hash does take more space than a similarly sized vector.

You Need to Know the Type Anyway

In practice, you need to know the type of an object before you can do anything useful with it. Say I have a variable called dave. How do I know if I can fire dave unless I know that dave is of type employee?

Can you think of any operation you can do on a variable without knowing the type? Stringify perhaps.

So, why was I making a big deal before?

Not having to know the exact type can give you a degree of genericity. I can have a whole bunch of things related to people that I can call age on. Maybe I’ll have an iterator field in a bunch of containers called iterator.

But really, I don’t care about that. I’m into aesthetics and I just like a terse language. I just find, dave.age, or even (*s dave.age) is much nicer than (person-age dave).