private IFn findAndCacheBestMethod(Object dispatchVal) throws Exception{
	Map.Entry bestEntry = null;
	for(Object o : getMethodTable())
		{
		Map.Entry e = (Map.Entry) o;
		if(isA(dispatchVal, e.getKey()))
			{
			if(bestEntry == null || dominates(e.getKey(), bestEntry.getKey()))
				bestEntry = e;
			if(!dominates(bestEntry.getKey(), e.getKey()))
				throw new IllegalArgumentException(
						String.format(
								"Multiple methods in multimethod '%s' match dispatch value: %s -> %s and %s, and neither is preferred",
								name, dispatchVal, e.getKey(), bestEntry.getKey()));
			}
		}
	if(bestEntry == null)
		return null;
	//ensure basis has stayed stable throughout, else redo
	if(cachedHierarchy == hierarchy.deref())
		{
		//place in cache
		methodCache = methodCache.assoc(dispatchVal, bestEntry.getValue());
		return (IFn) bestEntry.getValue();
		}
	else
		{
		resetCache();
		return findAndCacheBestMethod(dispatchVal);
		}
}