6

I have written a very simple nested If as follows

atom = be;

If[atom == li, lim = 5,

If[atom == be, lim = 3,

If[atom == b, lim = 2,

If[atom == c,
 lim = 1,

 If[atom == n,
  lim = 0.5,

  If[atom == o,
   lim = 0.3,

   If[atom == f,
    lim = 0.1,

    If[atom == ne,
     lim = 0.05;

     ]]]]]]]];

atom lim

but it works for atom=li namely just for first case, when I set atom=be for example it doesn't work and returns lim as unknown variable. What's wrong with it?

Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368
Wisdom
  • 1,258
  • 7
  • 13
  • Use Which instead of If? – cvgmt Dec 05 '21 at 06:41
  • 3
    Thanks but I want to know why this doesn't work?!! – Wisdom Dec 05 '21 at 06:42
  • do you see any problem in my code? – Wisdom Dec 05 '21 at 06:42
  • 1
    Style of your code is very un-Mathematica, but the root cause of your problem is that atom == li evaluates to be == li which is neither True or False. The correct approach is to use === instead of == on comparison. – kirma Dec 05 '21 at 06:55
  • 3
    If I were you, I'd consider some alternative approach, for instance atomlim = {li -> 5, be -> 3, b -> 2, c -> 1, n -> 0.5, o -> 0.3, f -> 0.1, ne -> 0.05}; atom = be; atom /. atomlim – kirma Dec 05 '21 at 07:03
  • @kirma Thanks, good idea – Wisdom Dec 05 '21 at 07:07
  • Why not use "li", "be" ... i.e. strings? lim[atom_] := If[atom == "li", 5, If[atom == "be", 3, If[atom == "b", 2, If[atom == "c", 1, If[atom == "n", 0.5, If[atom == "o", 0.3, If[atom == "f", 0.1, If[atom == "ne", 0.05, 99] ] ] ] ] ] ] ]; and lim[#] & /@ {"li", "be", "c", "n", "o", "f", "ne"} – Syed Dec 05 '21 at 07:10
  • @Syed because I had used them as iterator of an outer Do loop – Wisdom Dec 05 '21 at 07:12

3 Answers3

10

Change it to === and not == (examples at end)

Clear["Global`*"];
atom = be;
If[atom === li,
  lim = 5,
  If[atom === be,
   lim = 3,
   If[atom === b,
    lim = 2,
    If[atom === c,
     lim = 1,
     If[atom === n,
      lim = 0.5,
      If[atom === o,
       lim = 0.3,
       If[atom === f,
        lim = 0.1,
        If[atom === ne,
         lim = 0.05
         ]
        ]
       ]
      ]
     ]
    ]
   ]
  ];

And now

lim gives 3

Compare the difference

ClearAll[be];
atom = be;
If[atom == li, "yes", "no", "can not decide"]

gives "can not decide" but

ClearAll[be];
atom = be;
If[atom === li, "yes", "no"]

gives "no".

In your original code, you had == which worked as follows (it did not evaluate)

ClearAll[be];
atom = be;
If[atom == li, "yes", "no"]

It did not evaluate, since it could not decide and there was no third argument to use for the result of If, so it returned unevaluated.

Mathematica graphics

That is why your code did not evaluate.

Nasser
  • 143,286
  • 11
  • 154
  • 359
  • Thanks a lot. In general, can you tell me when should I use === instead of ==? – Wisdom Dec 05 '21 at 07:09
  • 1
    @Wisdom The rule of thumb I try to use is this: When you are working with symbols with no values, using ===. When working with things like numbers, strings, etc.. i.e. variables with actual values assigned to them, use == . Help says === that requires exact correspondence between expressions. See help on == and === for more details. For example, if you want to check the Head is say DSolve, then using === and not == since this is symbolic equality (sameQ). I think this topic is covered better in .... – Nasser Dec 05 '21 at 07:22
  • Thank you so much for your detailed comment, exactly I had used this code for numbers and it didn't had any problem and that is why I wondered it doesn't work here. Thanks again. – Wisdom Dec 05 '21 at 07:28
8

Alternative using Switch

Clear["Global`*"];
atom = be;
lim = Switch[atom,
  li, 5, be, 3, b, 2, c, 1, n, 0.5, o, 0.3, f, 0.1, ne, 0.05]

3

Chris Degnen
  • 30,927
  • 2
  • 54
  • 108
1

Alternative method:

atomLim["li"] = 5; 
atomLim["be"] = 3; 
atomLim["b"] = 2; 
atomLim["c"] = 1; 
atomLim["n"] = .5; 
atomLim["o"] = .3; 
atomLim["f"] = .1; 
atomLim["ne"] = .05; 

Then you can use atomLim["be"] which gives 3. This code should be faster than using multiple if statements. It is also possible to make this more manageable when the number of elements gets large (I don't know if you're planning to implement the entire periodic table lol)

elements = ToString /@ {li, be, b, c, n, o, f, ne};
limvalues = {5, 3, 2, 1, .5, .3, .1, .05};
Do[
 atomLim[elements[[i]]] = limvalues[[i]],
 {i, 1, Length@elements}]