Converting some LISP to C#

2019-07-01 11:02发布

问题:

I'm reading Paul Graham's A Plan for Spam and want to understand it better but my LISP is really rusty. He has a snippet of code that calculates probability as such:

(let ((g (* 2 (or (gethash word good) 0)))
      (b (or (gethash word bad) 0)))
   (unless (< (+ g b) 5)
     (max .01
          (min .99 (float (/ (min 1 (/ b nbad))
                             (+ (min 1 (/ g ngood))   
                                (min 1 (/ b nbad)))))))))

My question is twofold: (1) is there a web resource that will convert LISP to a different language? (my preference would be a C based language) or failing that (2) can someone rewrite that code snippet in C# for me?

回答1:

I think it's something like this (warning, possible errors ahead. This snippet is intended as a guide, not a solution):

var g = 2 * (gethash(word, good) | 0);
var b = gethash(word, bad) | 0;

if( (g + b) >= 5)
{
    return Math.Max( 
        0.01, 
        Math.Min(0.99, 
            Math.Min(1, b / nbad) / 
            (Math.Min(1, g / ngood) + Math.Min(1, b / nbad))));
}


回答2:

Adding on to Gonzola's answer, don't forget that Lisp provides infinite precision integers and rationals, while C# likes to truncate. You'll need to cast 'nbad' and 'ngood' to float first to get comparable (though not identical) results.

You may also want to put the whole converted program in a checked region. C# doesn't even warn on fixnum overflow -- the first approximation would be to treat overflow as if you're memory constrained (in Lisp, if overflow yeilds too big a number to fit in remaining memory, similar behavior results).

checked {
    var fbad = (double)nbad;
    var fgood = (double)ngood;
    var g = 2 * (gethash(word, good) | 0);
    var b = gethash(word, bad) | 0;


    if( (g + b) >= 5)
    {
        return Math.Max( 
            0.01, 
            Math.Min(0.99, 
                    Math.Min(1, b / fbad) / 
                    (Math.Min(1, g / fgood) + Math.Min(1, b / fbad))));
    }
}


标签: c# lisp