6
$\begingroup$

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?

$\endgroup$
8
  • $\begingroup$ Use Which instead of If? $\endgroup$
    – cvgmt
    Dec 5, 2021 at 6:41
  • 3
    $\begingroup$ Thanks but I want to know why this doesn't work?!! $\endgroup$
    – Wisdom
    Dec 5, 2021 at 6:42
  • $\begingroup$ do you see any problem in my code? $\endgroup$
    – Wisdom
    Dec 5, 2021 at 6:42
  • 1
    $\begingroup$ 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. $\endgroup$
    – kirma
    Dec 5, 2021 at 6:55
  • 3
    $\begingroup$ 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 $\endgroup$
    – kirma
    Dec 5, 2021 at 7:03

3 Answers 3

10
$\begingroup$

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.

$\endgroup$
4
  • $\begingroup$ Thanks a lot. In general, can you tell me when should I use === instead of ==? $\endgroup$
    – Wisdom
    Dec 5, 2021 at 7:09
  • 1
    $\begingroup$ @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 .... $\endgroup$
    – Nasser
    Dec 5, 2021 at 7:22
  • $\begingroup$ ... what-are-the-most-common-pitfalls-awaiting-new-users $\endgroup$
    – Nasser
    Dec 5, 2021 at 7:25
  • $\begingroup$ 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. $\endgroup$
    – Wisdom
    Dec 5, 2021 at 7:28
8
$\begingroup$

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

$\endgroup$
1
$\begingroup$

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}]
$\endgroup$
1
  • 1
    $\begingroup$ Instead of Do loop, you can also write: MapThread[Set[atomLim[#1], #2] &, {elements, limvalues}] $\endgroup$
    – polfosol
    Dec 6, 2021 at 17:29

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