1

I am supposed to show that two algorithms execute identical statements in identical order. One is a tail recursive version of the other. They are written in Eiffel.

tail_rec(x:instance_type):result_type is
    local
        y:instance_type;
    do
        if b(x) then
            Result :=c(x)
        else
            y:=d(x);
            Result:=tail_rec(y)
    end
  end

Then the non-tail recursive version.

non_rec(x:instance_type):result_type is
    do
        from until b(x) loop
            x:= d(x)
        end;
        Result:= c(x)
    end  

where b(x), c(x), and d(x) are any functions of type BOOLEAN, result_type, and instance_type respectively.

How are these two algorithms similar and how do they execute identical statements in identical order?

  • Are you sure this is right? This does not look like two different algorithms to me. It looks like the exact same algorithm implemented twice in two functions with identical bodies and different names. – Mike Nakis Mar 08 '15 at 19:41
  • @MikeNakis Like its said, one is tail recursive version of the other Edit: Actually you were right. Changed it to what it is supposed to be. –  Mar 08 '15 at 20:10

1 Answers1

0

By substituting all flow-of-control constructs with gotos, (essentially turning the code from Eiffel into pseudocode,) and allowing if statements to execute only gotos, it can be shown that both functions end up consisting of the exact same set of instructions.

Let me begin by copying the original tail_rec here for convenience:

tail_rec(x:instance_type):result_type is
    local
        y:instance_type;
    do
        if b(x) then
            Result := c(x)
        else
            y := d(x);
            Result := tail_rec(y)
        end
    end

First, get rid of Eiffel's silly Result := construct and replace it with return for convenience. (Otherwise, we are going to have to add more gotos, and frankly, the fewer the better.)

tail_rec(x:instance_type):result_type is
    local
        y:instance_type;
    do
        if b(x) then
            return c(x)
        end
        y := d(x);
        return tail_rec(y)
    end

Substitute the if-then-end with if-then goto:

tail_rec(x:instance_type):result_type is
    local
        y:instance_type;
    do
        if not b(x) then goto label1
        return c(x)
    label1:
        y := d(x);
        return tail_rec(y)
    end

Replace tail recursion with another goto:

tail_rec(x:instance_type):result_type is
    do
    label0:
        if not b(x) then goto label1
        return c(x)
    label1:
        x := d(x);
        goto label0
    end

Replace if not b(x) with if b(x):

tail_rec(x:instance_type):result_type is
    do
    label0:
        if b(x) then goto label1
        x := d(x);
        goto label0
    label1:
        return c(x)
    end

Similar transformations to tail_rec should turn it into the exact same thing.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142