Compare the two commands
a) sum(k,k=1..3); and
b) for k from 1 to 3 do print(k) od;
For (a), coming into the command, k must be unassigned but leaving the command, k has no assigned value.
For (b), coming into the command it doesn’t matter if k is assigned or not, but on leaving the command, k does have an assigned value.
So my question is, can someone give me some way to think about these two types of commands, to categorize them logically with others, so that I won’t continually make mistakes with them. It would be so much easier if these were consistent.
Here’s is a possible mnemonic for it:
In the first command, in the syntax, variable k is *accessed first, then assigned*.
In the second command, k is *assigned first, then accessed*.
It’s not a perfect statement of what’s really going on, but perhaps you can work with it.
sum is a Maple function implemented as a procedure, which evaluates its arguments before
doing anything with them, as do all procedures by default. Hence, if k has a value before
sum is executed, sum sees that value internally. sum(k,k=1..3)
is a Maple expression
consisting of a single function call, and in Maple an expression is a valid instance of a
statement.
(For this kind of explicit summation you should use the function add, which does not evaluate its arguments and behaves much more like the for loop.)
for k do ... is a Maple statement, which has completely different semantics from a function call. A statement in Maple is not an expression. There is no reason to expect it to behave similarly to sum.
It says use the variable k (not its value) as the loop counter in the following loop.
I suggest you stop thinking in terms of "commands", and instead think of expressions that evaluate to values and statements that do something and do not evaluate to anything.
(a) "sum" is a procedure and applying a procedure
(1) implies full evaluation of the arguments;
(2) doesn’t affect the value of the arguments.
So
k := 10: sum(k,k=1..3); evaluates to sum(10,10=1..3);
There are some exceptions
(1) the arguments of eval, evalf, seq and traperror are not evaluated
(2) arguments with type array or table only evaluate to the last name, i.e. if you have
A := : B := A: then foo(B); evaluates to foo(A) and not to foo( array(1..2,[p,q]) )
(3) Some procedures can have names as arguments that can get a value by the procedure.
(b) In a loop like
for k from 1 to 3 do print(k) od;
the first thing done is the assignment k := 1
and this works even if k has already a value.
When the loop ends the last thing done is the assignment k := 4
(followed by something
like: if k>3
then leave)
I happen to have posted a couple weeks ago, to our internal group of Maple developers, a response related to what you are mentioning above.
The main point: Consistency holds among "add", "mul", "seq", ... .
The "sum" and "product" commands are in a different category – consistent with "int" as alluded to in my message below.
Most often, users really want to be using "add" not "sum". Use "add" for explicit summation of values. Use "sum" only for symbolic summation.
It looks to me that sum needs special evaluation rules. Consider:
Well ... this has been long-debated in the past and I believe the correct conclusion was made.
While your one type of example here would "work well" with the special evaluation rules you propose, other examples would "not work well".
Consider the analogy between sum and int. Should int(f, x) *not* evaluate f? It has to, and it does.
I believe that both sum and int must evaluate their arguments as at present.
What the user needs to be pointed to is: Use add (not sum) for the type of situations in your example below.
> f:=proc(n) if (n mod 2)=0 then 1 else -1 fi end; f := proc(n) if n mod 2 = 0 then 1 else -1 end if end proc > sum(f(n),n=0..50); -51 > sum('f(n)',n=0..50); 1
I think the average user is not expected to delay evaluation - the first argument to sum should be of type uneval.
Here is how it works with add (to the user’s delight!) –
> f:=proc(n) if (n mod 2)=0 then 1 else -1 fi end; f := proc(n) if n mod 2 = 0 then 1 else -1 end if end proc > add(f(n),n=0..50); 1
A possible reason that you are having problems is that you are using sum when you should be using add. While the syntax of add is similar to sum, the summation variable in add is always local to the function, that is, it doesn’t matter whether a variable of the same name has been assigned.
sum is intended to be used for symbolic summations. As such, it must be able to work with existing expressions. add, on the other hand, must have the summation variable explicitly included within the expression. To see this, consider the following
proc() local y; y := i^2; [sum(y,i=1..3),add(y,i=1..3)] end(); [14, 3*i^2]
The add function gave a different result because its summation variable i is different from the variable i in y. From this it is apparent (I believe) that the summation variable for a sum "must" be unassigned. Otherwise the expression to be summed is meaningless.