Message Boards Message Boards

0
|
3568 Views
|
7 Replies
|
2 Total Likes
View groups...
Share
Share this post:

Why inserting a command into a procedure yields error

Posted 2 years ago

I have a square matrix m to which I want to assign new values into its diagonal. For example,

m={
  {20, 24, 33, 36, 34},
  {39, 13, 15, 30, 30},
  {18, 17, 16, 28, 27},
  {39, 35, 33, 32, 37},
  {30, 21, 22, 10, 23}
}

I want to change the diagonal elements into some negative numbers:

Table[
 m[[i, i]] = RandomInteger[-10, Length[m]]〚i〛,
 {i, 1, Length[m]}]

That works just fine.

Now I want to write a function f1 that performs this manipulation, and this is where I got stuck:

f1[q_] := Table[
  q[[i, i]] = RandomInteger[{-10, 0}, Length[q]]〚i〛,
  {i, 1, Length[q]}]

f1[m]

gives

Set::setps: {{20,24,33,36,34},{39,13,15,30,30},{18,17,16,28,27},{39,35,33,32,37},{30,21,22,10,23}} in the part assignment is not a symbol.

Set::setps: {{20,24,33,36,34},{39,13,15,30,30},{18,17,16,28,27},{39,35,33,32,37},{30,21,22,10,23}} in the part assignment is not a symbol.

Set::setps: {{20,24,33,36,34},{39,13,15,30,30},{18,17,16,28,27},{39,35,33,32,37},{30,21,22,10,23}} in the part assignment is not a symbol.

General::stop: Further output of Set::setps will be suppressed during this calculation.

Why is that?

POSTED BY: Ehud Behar
7 Replies

Hi Ehud

What you are trying is called side effect programming which is considered as bad style and should be generally avoided in any programming. In partikular you are trying to pass a parameter by reference which is not the "Mathematica Way" .

It is better to generate a new object.

ReplacePart[m, {{i_, i_}} :> RandomInteger[-10]]

m=ReplacePart[m, {{i_, i_}} :> RandomInteger[-10]]

f1[q_] := ReplacePart[q, {{i_, i_}} :> RandomInteger[-10]]
m = f1[m]
POSTED BY: Robert Nowak
Posted 2 years ago

Totally agree with you. Thanks a lot for pointing that out and providing this nice solution.

POSTED BY: Ehud Behar
Posted 2 years ago

I will try to give a condensed explanation.
By default a function argument is evaluated before it is passed on to the functions body. So the argument q becomes an explicit 5x5 matrix when it is seen as the left hand side of the assignment in Table.

And the assignment lhs[[x]]=rhs works only if lhs is a symbol. If not it gives the error you saw.

Unevaluated prevents evaluation of the argument. So q becomes the symbol m.

POSTED BY: Hans Milton
Posted 2 years ago

Another way

SetAttributes[f1, HoldFirst]
POSTED BY: Rohit Namjoshi
Posted 2 years ago

Yes Rohit, Unevaluated and the function attribute HoldFirst gives the same effect in this case. But one could argue that Unevaluated is more 'entry level' and easier to explain.

POSTED BY: Hans Milton
Posted 2 years ago

Try to wrap Unevaluated around the argument when calling f1

f1[Unevaluated[m]]
POSTED BY: Hans Milton
Posted 2 years ago

Lo and behold. Works.

Could you explain why?

POSTED BY: Ehud Behar
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract