GenericUDF are more powerful than UDF in the following ways:
1. It can accept arguments of complex types, and return complex types.
2. It can accept variable length of arguments.
3. It can accept an infinite number of function signature - for example, it's easy to write a GenericUDF that accepts array<int>, array<array<int>> and so on (arbitrary levels of nesting).
4. It can do short-circuit evaluations.