public EvaluationResult evaluate(List inputs, EvaluationCtx context) {

        // Evaluate the arguments
        AttributeValue [] argValues = new AttributeValue[inputs.size()];
        EvaluationResult evalResult = evalArgs(inputs, context, argValues);
        if (evalResult != null)
            return evalResult;

        // setup the two bags we'll be using
        BagAttribute [] bags = new BagAttribute[2];
        bags[0] = (BagAttribute)(argValues[0]);
        bags[1] = (BagAttribute)(argValues[1]);

        AttributeValue result = null;
        
        switch(getFunctionId()) {
            // *-at-least-one-member-of takes two bags of the same type and
            // returns a boolean
        case ID_BASE_AT_LEAST_ONE_MEMBER_OF:
            // true if at least one element in the first argument is in the
            // second argument (using the *-is-in semantics)

            result = BooleanAttribute.getFalseInstance();
            Iterator it = bags[0].iterator();

            while (it.hasNext()) {
                if (bags[1].contains((AttributeValue)(it.next()))) {
                    result = BooleanAttribute.getTrueInstance();
                    break;
                }
            }
            
            break;

            // *-set-equals takes two bags of the same type and returns
            // a boolean
        case ID_BASE_SUBSET:
            // returns true if the first argument is a subset of the second
            // argument (ie, all the elements in the first bag appear in
            // the second bag) ... ignore all duplicate values in both
            // input bags

            boolean subset = bags[1].containsAll(bags[0]);
            result = BooleanAttribute.getInstance(subset);
            
            break;

            // *-set-equals takes two bags of the same type and returns
            // a boolean
        case ID_BASE_SET_EQUALS:

            // returns true if the two inputs contain the same elements
            // discounting any duplicates in either input ... this is the same
            // as applying the and function on the subset function with
            // the two inputs, and then the two inputs reversed (ie, are the
            // two inputs subsets of each other)

            boolean equals = (bags[1].containsAll(bags[0]) &&
                              bags[0].containsAll(bags[1]));
            result = BooleanAttribute.getInstance(equals);

            break;
        }
        
        return new EvaluationResult(result);
    }