That is a good question. The call to sum returns 0 because it is summing 0. That is, the call to G is evaluated before it is passed to sum. With symbolic arguments i and j G returns 0. There are two ways to avoid that: (1) modify G so that it returns unevaluated unless its arguments are numeric; and (2) modify the usage of G so that it doesn't get fully evaluated until being passed to sum. Let's tackle these in order.
Modifying G is the more useful technique. Change it so that it returns an unevaluated call to itself when it arguments are not numeric.
G := proc(i,j)
if not [args]::list(numeric) then return 'G'(i,j) fi;
if [i,j]::list(even) then return 1 else return 0 end if;
sum( sum( G(i,j), i=0..5 ), j=0..5 );
Modify the call to sum
The usual way to do this is to enclose the argument in forward quotes.
At the user level you will need two pairs of forward quotes:
G := (i,j) -> if is(i,even) and is(j,even) then 1; else 0; end if;
sum( sum( ''G''(i,j), i=0..5 ), j=0..5 );
You might be wondering why sum isn't designed to work like add, which avoids these problems. Add is able to avoid them because it uses
special evaluation rules. Doing the equivalent with sum would not be useful, the reason being that sum is intended to evaluate summations and must be able to operate on expression generated outside the sum function. The summation index is not local to the sum. To see the problem do
y := i^2;
return [add,sum](y, i = 1..3);
[3 i , 14]
The sum returns the intended value, the add does not.