Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I REALLY do math with NSNumbers? (implementing a lisp in obj-c)

inspired by Clojure, and Peter Norvig

I have been trying my hand at implementing a simple Lisp in obj-c. I have many of the basics (including some cool cocoa integration similar to Clojure) working and would like to move on to arithmetic.

A little background on how I have implemented this so far: I am using a tiny class "Scope", which is just an NSMutableDictionary for local vars, with a pointer to a parent "Scope". (AKA, I am constrained to only storing objects.)

I parse numbers with the following rule: a plain number like 2, or 2.7, gets converted to an [NSNumber numberWithIneger:] or [NSNumber numberWithDouble:]. But for cocoa integration you can also do things like 2i, or 4U, to create the NSNumber with a specific scalar type. (I also created a category around NSObject and made a new method performSelector:withObjects: that smartly unboxes the args, and boxes back up the return type to actually make this useful)

I have a special form that looks like: (static Math add: 1 2 3 4), which would turn into a obj-c method call that looks like: [Math add:args]

Given all this, my question to all of you fine folks is: what's a good way to implement the "add:" method?

I was hoping to do something similar to how I believe clojure does (use to do?) it, by implementing a bunch of methods like add:(int)x to:(long)y, add:(long)x to:(float)y, etc, etc, through all possible combinations, and reducing over the args list pair-wise adding everything. But of course, obj-c doesn't support overriding methods like that. Other than constraining myself to only addition on NSIntegers and doubles, is there any kind of trickery I can do to get where I want? I don't even really care if it's super efficient (though, that's always a plus!)

like image 639
Bob White Avatar asked Jun 16 '11 18:06

Bob White


1 Answers

Easy method: simply turn all numbers into doubles when doing arithmetic, and ignore casting and precision issues.

Another option is to use NSDecimalNumber instead of NSNumber everywhere. There's the +[NSDecimalNumber decimalNumberWithString] method that you could use for boxing, and there are also methods for performing arithmetic with multiple NSDecimalNumbers. Of course, you have more overhead this way, but I imagine raw performance is not a primary concern.

like image 143
Daniel Dickison Avatar answered Nov 28 '22 05:11

Daniel Dickison