10
$\begingroup$

I am new to Mathematica so this question may seem rudimentary. Sorry for that! :)

I want to implement the well-known property of Kronecker's Delta

$$\Sigma_{i=1}^{n} a_i \delta_{ij}=a_j,\quad 1 \le j \le n$$

So I wrote the following code

KroDelProp[Eq_] := Module[{R, c, i, j, a, b},
  R = Inactive[Sum][c_*KroneckerDelta[i_, j_], {i_, a_, b_}] :> (c /. i -> j);
  Eq /. R
  ]
Eq = Inactive[Sum][a[i]*KroneckerDelta[i, j], {i, 1, n}]
KroDelProp[Eq]
(* a[j] *)

So everything looks fine. But when I use Rule instead of RuleDelayed in KroDelProp then I get

KroDelProp[Eq_] := Module[{R, c, i, j, a, b},
  R = Inactive[Sum][c_*KroneckerDelta[i_, j_], {i_, a_, b_}] -> (c /. i -> j);
  Eq /. R
  ]
Eq = Inactive[Sum][a[i]*KroneckerDelta[i, j], {i, 1, n}]
KroDelProp[Eq]
(* a[i] *)

I read the documentation but I couldn't find out what is happening here!

Can someone shed some light on this? :)


I found reading this documentation very useful. Hope that it helps the future readers of this post too.

$\endgroup$
  • $\begingroup$ I invite you to read the documentation that the first sentence could not be more explicit. Rule "represents a rule that transforms lhs to rhs." RuleDelayed "represents a rule that transforms lhs to rhs, evaluating rhs only after the rule is used." $\endgroup$ – physicien Mar 25 '16 at 14:58
  • 1
    $\begingroup$ @physicien: I read that but I couldn't find why this happens! Why the evaluation of RHS of the rules effects the output here? $\endgroup$ – H. R. Mar 25 '16 at 15:00
  • $\begingroup$ @physicien: Can you tell what happens in each of the codes step by step? $\endgroup$ – H. R. Mar 25 '16 at 15:04
  • $\begingroup$ @physicien: I had a typo. I mean that the output is $a[i]$ or $a[j]$ in each case. $\endgroup$ – H. R. Mar 25 '16 at 15:14
  • 1
    $\begingroup$ Try x = 17; {y -> x, y :> x} $\endgroup$ – John Doty Mar 25 '16 at 15:22
6
$\begingroup$

Perhaps the easiest way to highlight the differences is to isolate the substitution rules you constructed in each case. See what the following rules evaluate to:

(* Rule *)
Inactive[Sum][c_*KroneckerDelta[i_, j_], {i_, a_, b_}] -> (c /. i -> j)

immediate

(* RuleDelayed *)
Inactive[Sum][c_*KroneckerDelta[i_, j_], {i_, a_, b_}] :> (c /. i -> j)

delayed

You can clearly see that in the first case (simple Rule), the right hand side of the rule is immediately evaluated; in that case c does not contain i so the second replacement in RHS doesn't apply, and the RHS just evaluates to c. When you apply this substitution rule, c matches a[i] in the expression, so that's what's returned.

With RuleDelayed evaluation of the right hand side is delayed until after a match has been found. In this case, c matches to a[i]; the right hand side then evaluates to a[i] /. i -> j, which produces the correct result.

$\endgroup$
  • $\begingroup$ Thanks for the comprehensive answer. :) I am happy now! :D $\endgroup$ – H. R. Mar 25 '16 at 17:36
  • 1
    $\begingroup$ @H.R. Glad it helped! Your question provides a nice practical example of the difference in behavior between Rule and RuleDelayed. $\endgroup$ – MarcoB Mar 25 '16 at 17:38
2
$\begingroup$

It's always useful to see what the fragments of your code do. Compare the result of:

Inactive[Sum][c_*KroneckerDelta[i_, j_], {i_, a_, b_}] :> (c /. i -> j)

With:

Inactive[Sum][c_*KroneckerDelta[i_, j_], {i_, a_, b_}] -> (c /. i -> j)

Note also that localizing the names of patterns with Module does nothing, and there's no need to name your rule. And then, why not pattern match in your definition, deconstruct your argument there?

KroDelProp[Inactive[Sum][c_*KroneckerDelta[i_, j_], {i_, a_, b_}]] := c /. i -> j
KroDelProp[Inactive[Sum][a[i]*KroneckerDelta[i, j], {i, 1, n}]]

(* a[j] *)

Module is rarely useful. It's usually a symptom that you could factor your code better.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.