Search code examples
javaschemecode-translation

Help me translate this Java to Scheme to get things going in my head


I am learning Scheme, and I've read the basics but I still can't figure how to "map" a Java class to Scheme code. Could any of you guys help me out here? I just need someone to show me how this looks in Scheme to grasp the final details and get things going in my head:

public class sumFibonacciValues {
    public static void main(String [] args) {
        int n = 4000000;
        long i2 = 1, i1 = 1, Fibo = 0, temp = 1;
        while(i2 < n) {
            temp = i1 + i2;
            i1 = i2;
            i2 = temp;
            if(i2 % 2 == 0)
                Fibo += i2;
        }
        System.out.println(Fibo);
    }
}

Solution

  • I wouldn't have answered something that looks so much like homework, but the "idiomatic" comment just begged for a demonstration that it's really not that far. First, a direct translation:

    (define (sum-fibonacci-values)
      (define n 4000000)
      (define i2 1)
      (define i1 1)
      (define fibo 0)
      (define temp 1)
      (let loop ()
        (when (< i2 n)
          (set! temp (+ i1 i2))
          (set! i1 i2)
          (set! i2 temp)
          (when (zero? (modulo i2 2)) (set! fibo (+ fibo i2)))
          (loop)))
      (write fibo))
    

    Second, make it "idiomatic", by removing the redundant mutations, and instead just bind new values, and using a tail-recursive loop. Note that this code is still in direct correlation with the original:

    (define (sum-fibonacci-values)
      (define n 4000000)
      (let loop ([i2 1] [i1 1] [fibo 0] [temp 1])
        (if (< i2 n)
          (let* ([temp (+ i1 i2)]
                 [i1 i2]
                 [i2 temp]
                 [fibo (if (zero? (modulo i2 2)) (+ fibo i2) fibo)])
            (loop i2 i1 fibo temp))
          fibo)))
    

    Finally, now that the code is clearer, you can see that there are some redundancies. Here's a cleaned up version:

    (define (sum-fibonacci-values)
      (define n 4000000)
      (let loop ([i2 1] [i1 1] [fibo 0])
        (if (< i2 n)
          (let ([i3 (+ i1 i2)])
            (loop i3 i2 (if (zero? (modulo i3 2)) (+ fibo i3) fibo)))
          fibo)))
    

    Note that the same cleanup can be done on the Java code. (But that's really left as an exercise to the reader...)