10

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.

Hosein Rahnama
  • 1,727
  • 1
  • 15
  • 29
  • 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."

    – physicien Mar 25 '16 at 14:58
  • 1
    @physicien: I read that but I couldn't find why this happens! Why the evaluation of RHS of the rules effects the output here? – Hosein Rahnama Mar 25 '16 at 15:00
  • @physicien: Can you tell what happens in each of the codes step by step? – Hosein Rahnama Mar 25 '16 at 15:04
  • @physicien: I had a typo. I mean that the output is $a[i]$ or $a[j]$ in each case. – Hosein Rahnama Mar 25 '16 at 15:14
  • 3
    Try x = 17; {y -> x, y :> x} – John Doty Mar 25 '16 at 15:22
  • I'm no expert, but I think the problem is in -> (c /. i -> j). I think it's because Rule tries to evaluate directly instead of waiting to be used, so as there is nothing to evaluate, it returns the value it had previously. – physicien Mar 25 '16 at 15:28
  • @JohnDoty: Thanks. :) Can you kindly write an answer? :) I will be so thankful if you address what happens in each of the codes above. :) In fact, why the outputs differ? – Hosein Rahnama Mar 25 '16 at 17:09
  • @H.R. I think a nice simple example of this is as follows--

    rule={a -> Print["a Evaluated"], b :> Print["b Evaluated"]};

    and

    b/.rule

    evaluate that and see what happens

    – enano9314 Jul 14 '16 at 23:26

2 Answers2

6

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.

MarcoB
  • 67,153
  • 18
  • 91
  • 189
2

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.

John Doty
  • 13,712
  • 1
  • 22
  • 42