-7
$\begingroup$

I have the module who should replace some elements of a matrix with checkboxes

addChekboxesTable[x0_] := Module[{x = x0},
  For[i = 1, i <= Length[x], i++,
    For[j = 1, j <= Length[x[[i]]], j++,
     If[x[[i, j]] == "x",
       x[[i, j]] = Checkbox[True];
       ]
      If[x[[i, j]] == "o",
       x[[i, j]] = Checkbox[False];
       ]
      If[x[[i, j]] == "u",
       x[[i, j]] = Checkbox[3, {1, 2, 3}];
       ]
     ]
    ]
   x
  ]

I call the module like:

pp = addChekboxesTable[{{"Datatype", "Variable Name", "S0", "S1", 
     "x"}}];

And then the string is corrupted :( It has some Nulls and Times

List[List[Times["Datatype",Null],Times["Variable Name",Null],Times["S0",Null],Times["S1",Null],Times[Null,Checkbox[True]]]]

I dont know why :(( Any ideas ?

Ps: if i extract the instruction from module, outside , the code works O_O

I changed the function to the next for by adding some ";" at the end of instructions. It fixed but i dont know why O_O

addChekboxesTable[x0_] := Module[{x = x0},
  For[i = 1, i <= Length[x], i++,
   For[j = 1, j <= Length[x[[i]]], j++,
     If[x[[i, j]] == "x",
      x[[i, j]] = Checkbox[True];
      ];
     If[x[[i, j]] == "o",
      x[[i, j]] = Checkbox[False];
      ];
     If[x[[i, j]] == "u",
      x[[i, j]] = Checkbox[3, {1, 2, 3}];
      ];
     ];
   ];
  x
  ]
$\endgroup$
7
  • 1
    $\begingroup$ I would suggest putting a ; after each If like If[stuff]; What you have written is If[stuff] * If[more] * If[even more] * x. In Mathematica a b c is abc. $\endgroup$
    – Ymareth
    Commented Dec 18, 2014 at 16:07
  • $\begingroup$ i did and didnt solve the corruption $\endgroup$
    – TraceKira
    Commented Dec 18, 2014 at 16:13
  • $\begingroup$ Did it change the result? $\endgroup$
    – Ymareth
    Commented Dec 18, 2014 at 16:14
  • $\begingroup$ NO it didnt change the result $\endgroup$
    – TraceKira
    Commented Dec 18, 2014 at 16:15
  • 8
    $\begingroup$ it is not a hack to use proper syntax $\endgroup$
    – chuy
    Commented Dec 18, 2014 at 16:25

2 Answers 2

4
$\begingroup$

There is a missing semicolon just behind the end of the outer For, just before the x, corrected below.

addChekboxesTable[x0_] := Module[{x = x0}, 
  For[i = 1, i <= Length[x], i++, 
   For[j = 1, j <= Length[x[[i]]], j++, 
    If[x[[i, j]] == "x", x[[i, j]] = Checkbox[True];] If[
      x[[i, j]] == "o", x[[i, j]] = Checkbox[False];] If[
      x[[i, j]] == "u", x[[i, j]] = Checkbox[3, {1, 2, 3}];]]]; x]

The result of the For block is Null so the result, without that semicolon, is Null times x.

$\endgroup$
4
  • $\begingroup$ The result of the For is not Null or else the code would NOT loop over the elements $\endgroup$
    – TraceKira
    Commented Dec 18, 2014 at 16:30
  • 1
    $\begingroup$ Unless an explicit Return is used, the value returned by For is Null. $\endgroup$
    – chuy
    Commented Dec 18, 2014 at 16:35
  • $\begingroup$ @timoftebogdan See (details section) here... reference.wolfram.com/language/ref/For.html Like a many Mathematica functions with side effects For returns Null (unless as Chuy points out you explicitly return something from it). That doesn't mean it doesn't do anything. $\endgroup$
    – Ymareth
    Commented Dec 18, 2014 at 16:40
  • 2
    $\begingroup$ Mathematica is a functional language (mostly). Everything returns something. Those functions that operate mostly through side effects (like say, Do, For, Scan, Print) return Null. That aside, I'd suggest you take a look at replacement rules as I think that would make your code simpler. $\endgroup$
    – Ymareth
    Commented Dec 18, 2014 at 16:51
8
$\begingroup$

Replacement rules make this much easier, as Ymareth indicated.

Make a list of rules like:

r2 = {"x" -> Checkbox[True], "o" -> Checkbox[False], 
   "u" -> Checkbox[3, {1, 2, 3}]};

Then apply these to the matrix m as:

m/.r2

Note that this code is idiomatic Mathematica and imminently readable by anyone familiar with it. Nested For loops and term by term rewriting are both strongly discouraged in Mathematica - and not just for aesthetic reasons - rule based and functional programming are typically much more efficient. Let's compare the two approaches. First, we'll generate a matrix of characters, which is (admittedly) absurdly large to illustrate the point.

m = RandomChoice[{"x", "o", "j"}, {1000, 1000}];

OK, let's try out the approach here:

mOut = m /. r2;  // AbsoluteTiming
mOut[[1;;10,1;;10]] // Grid
(* Out: {0.275804, Null} *)

enter image description here

Just over a quarter second - and looks good too! Let's try the other approach.

addChekboxesTable[m]; // AbsoluteTiming
(* Out: {58.618144, Null} *)

Nearly a full minute.

$\endgroup$
3
  • $\begingroup$ he already answered.Also this code is unreadable.My code is much beautifull !(procedural programming ftw !) $\endgroup$
    – TraceKira
    Commented Dec 18, 2014 at 20:56
  • 3
    $\begingroup$ +1 @TraceKira This code is much more idiomatic and easily readable by anyone who is familiar with Mathematica. This style of programming is also much more efficient in Mathematica, as I've tried to illustrate in my edit. $\endgroup$ Commented Dec 19, 2014 at 0:55
  • 2
    $\begingroup$ @TraceKira If you try to stick with procedural programming in Mathematica your experience will be painful. You are strongly advised to (gradually) embrace the functional style. $\endgroup$
    – Ymareth
    Commented Dec 19, 2014 at 8:52

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