@Override
        public Object apply(Object input) {
            if (input instanceof List) {
                List<Object> newList = Lists.newArrayListWithExpectedSize(((List) input).size());
                for (Object val : (List) input) {
                    newList.add(COPY.apply(val));
                }
                return newList;
            } else if (input instanceof OperatorNode) {
                return ((OperatorNode) input).copy();
            } else if (input instanceof String || input instanceof Number || input instanceof Boolean) {
                return input;
            } else {
                // this may be annoying but COPY not understanding how to COPY and quietly reusing
                // when it may not be immutable could be dangerous
                throw new IllegalArgumentException("Unexpected value type in OperatorNode tree: " + input);
            }
        }
Represents a use of an operator against concrete arguments. The types of arguments depend on the operator.
The extension point of this scheme is the Operator rather than new types of Nodes.
Operators SHOULD take a fixed number of arguments -- wrap variable argument counts in Lists.
container-search/src/main/java/com/yahoo/search/yql/OperatorNode.java