on run script ratioString -- Using a tolerance epsilon of 1/10000 on |λ|(x) showRatio(approxRatio(1.0E-4, x)) end |λ| end script map(ratioString, ¬ {0.9054054, 0.518518, 0.75}) --> {"67/74", "14/27", "3/4"} end run -- approxRatio :: Real -> Real -> Ratio on approxRatio(epsilon, n) if {real, integer} contains (class of epsilon) and 0 < epsilon then set e to epsilon else set e to 1 / 10000 end if script gcde on |λ|(e, x, y) script _gcd on |λ|(a, b) if b < e then a else |λ|(b, a mod b) end if end |λ| end script |λ|(abs(x), abs(y)) of _gcd end |λ| end script set c to |λ|(e, 1, n) of gcde Ratio((n div c), (1 div c)) end approxRatio -- Ratio :: Int -> Int -> Ratio on Ratio(n, d) {type:"Ratio", n:n, d:d} end Ratio -- showRatio :: Ratio -> String on showRatio(r) (n of r as string) & "/" & (d of r as string) end showRatio -- GENERIC FUNCTIONS --------------------------------------------- -- abs :: Num -> Num on abs(x) if 0 > x then -x else x end if end abs -- Lift 2nd class handler function into 1st class script wrapper -- mReturn :: First-class m => (a -> b) -> m (a -> b) on mReturn(f) if class of f is script then f else script property |λ| : f end script end if end mReturn -- map :: (a -> b) -> [a] -> [b] on map(f, xs) tell mReturn(f) set lng to length of xs set lst to {} repeat with i from 1 to lng set end of lst to |λ|(item i of xs, i, xs) end repeat return lst end tell end map