RPN-Stack-Based Recursive Calculator Needs Tuneup This function takes an array of strings and numbers and recursively processes it as a kind of "calculating program".  The structure is based on Reverse Polish Notation, so the top object in the stack (last in the array) determines what to do with the next one (or two) items in the program.  For example, if the array was [1, 2, "+"], the solution would be 3.  


In the case of errors, it should return an NSString describing the
error that happened.  
If more than one error occurs in processing, it is not clear which
error should receive priority, so I've chosen to prioritize the first
error found and ignore any further errors.


I think that this code could be made much more simple, but I'm not sure how best to do that in Objective C.  What suggestions do you have to improve this code?

 + (id)popOperandOffProgramStack:(NSMutableArray *)stack
    {
        id result;
        double dResult;

        id topOfStack = [stack lastObject];
        if (topOfStack) [stack removeLastObject];

        if ([topOfStack isKindOfClass:[NSNumber class]])
        {
            result = topOfStack;
        }
        else if ([topOfStack isKindOfClass:[NSString class]])
        {
            id rightSide = [self popOperandOffProgramStack:stack];
            if (![rightSide isKindOfClass:[NSNumber class]]) {
                return rightSide;
            }
            double r = [(NSNumber *)rightSide doubleValue];

            NSString *operation = topOfStack;
            if ([[self class] isBinaryOperation:operation]) {
                id leftSide = [self popOperandOffProgramStack:stack];
                if (![leftSide isKindOfClass:[NSNumber class]]) {
                    return leftSide;
                }
                double l = [(NSNumber *)leftSide doubleValue];
                if([operation isEqualToString:@"+"]) {
                    dResult =  l + r;
                } else if([operation isEqualToString:@"-"]) {
                    dResult = l - r;
                } else if([operation isEqualToString:@"*"]) {
                    dResult = l * r;
                } else if([operation isEqualToString:@"/"]) {
                    if(r == 0.0) {
                        return @"Error: Tried to divide by zero";
                    } else {
                        dResult = l / r;
                    }
            }
            } else if ([operation isEqualToString:@"+/-"]) {
                dResult = -r;  
            } else if([operation isEqualToString:@"sin"]) {
                dResult = sin(r);
            } else if([operation isEqualToString:@"cos"]) {
                dResult = cos(r);
            } else if([operation isEqualToString:@"sqrt"]) {
                if(r &lt; 0) {
                    return @"Error: tried to sqrt a negative number";
                }
                dResult = sqrt(r);
            } else if([operation isEqualToString:@"π"]) {
                dResult = 3.141592654;
            } else {
                /* unknown operations and unset variables will return 0 */
                dResult = 0.0;
            }
            result = [NSNumber numberWithDouble:dResult];
        }
        return result;
    }
Instead of returning an error-String, I would pass in a nil'ed-NSError object by reference, and write an error to it, in case it occurred. the returned object would be nil

+ (NSNumber *)popOperandOffProgramStack:(NSMutableArray *)stack error:(NSError **)error
{
    //…
    error = [[NSError alloc] int…] ;
}


Usage:

NSError *error = nil;
if ([Calculator popOperandOffProgramStack:parameters error:&amp;error])
{
    //returned object not nil -&gt; success
} else {
    //nil-object -&gt; let's check the error 
}


this avoids type checking.