You know, DWIM is nice and all, but at some point you need to step back and accept that some things carry real meaning and should not be changed lightly.
Positions move around dynamically. Naming things is more robust to future changes than remembering positions. Hence the value of hashes.
Beyond that if you want more flexibility in the face of changes to names, you need to add a level of indirection to the naming. An indirection layer, whether it is a hash lookup in your code from external names to internal names used in code (so you only need to change one thing to external changes), or some sort of meta-table from which you drive other tables, gives you more protection. Remember that adding a level of indirection can solve all problems except the problem of having too many layers of indirection!
However worrying about piling layers upon layers of indirection on right away, before you have concrete examples to work with, is a warning sign for a design process run amock with people who probably should not be designing. (For some reason OO lends itself far too naturally to this sort of problem.) You need to strike a balance between practicality and theory. And you need to accept that it is the nature of the beast that often good generalizations can only become apparent in the light of practical experience.
You know, good design is not about following some abstract rules. Polymorphism isn't good in and of itself. Abstraction is not an ideal goal. Modularity is not the measure of all code. Instead the rules are abstractions of lessons learned by hard experience about things that have practical value.
One thing that I see about you is this tendancy towards memorized facts. You seem to have little understanding of principles. Sure, eliminating repetitive typing is good. Do you understand why? Do you understand why, despite that principle, it is better to put all of your functions in @EXPORT_OK instead of @EXPORT and force people to repetitively type what functions they want? (So much so that Exporter's documentation specifically recommends that?)
You mentioned once that you don't like living with your own designs. Having seen the questions you ask, I can understand why you would not. Take this question. You want to produce the ultimate polymorphic doo-dad. Why? I suspect that you would be better off putting a layer of indirection (say through a hash that you eventually populate from a lookup table) between the names in the tables and the labels on the front end, then try to choose good names for both. If the labels change, you have to retype something. Minor ouch. Most changes will be pretty easy to make though, so it isn't a big deal. (Make sure it crashes pretty obviously on bad names, best to find that oops quickly.) But if someone else wants to read your code, they will be able to figure out what is going on. This is a Really Big Deal. And most importantly, you won't get into a situation where someone makes a change, the program guesses what they meant and gets it wrong, and nobody finds out for 6 months. Do you understand why this is important to prevent?
OK, I won't continue beating around the point. My point is that I would design this with a layer of indirection so that your code can be easily altered to handle a new world order, but should fall apart in a very noticable way if names change and no human intervenes. IMNSHO the way you asked your question shows a lack of awareness of basic principles of what I would call "good taste".
In reply to Re (tilly) 1: Topics in Perl Programming: Table-Mutation Tolerant Database Fetches with DBI