title: R: IF statement evaluating expression despite condition being FALSE?
body: <p>I've got a large function in R and the users have the ability to not include/specify an object. If they DO, the code checks to make sure the names in that object match the names in another. If they DON'T, there's no need to do that checking. The code line is:</p>
  
  <pre><code>if(exists("grids")) if(!all(expvarnames %in% names(grids))) {stop("Not all expvar column names found as column names in grids")}
  </code></pre>
  
  <p>But I'm getting the following error:</p>
  
  <pre><code>Error in match(x, table, nomatch = 0L) : argument "grids" is missing, with no default
  </code></pre>
  
  <p>Well in this trial run, grids is SUPPOSED to be missing. If I try</p>
  
  <pre><code>if(exists("grids")) print("yay")
  </code></pre>
  
  <p>Then nothing prints, i.e. the absence of grids means the expression isn't evaluated, which is as I'd expect. So can anyone think why R seems to be evaluating the subsequent IF statement in the main example? Should I slap another set of curly brackets around the second one??</p>
  
  <p>Thanks!</p>
  
  <p>Edit: more problems. Removing "grids," from the functions list of variables means it works if there's no object called grids and you don't specify it in the call (i.e. <code>function(x,grids=whatever)</code>). And keeping "grids," IN the functions list of variables means it works if there IS an object called grids and you do specify it in the call.</p>
  
  <p>Please see this: <a href="http://i.imgur.com/9mr1Lwi.png" rel="nofollow">http://i.imgur.com/9mr1Lwi.png</a></p>
  
  <p>using <code>exists(grids)</code> is out because exists wants "quotes" and without em everything fails. WITH them ("grids"), I need to decide whether to keep "grids," in the functions list. If I don't, but I specify it in the call <code>(function(x,grids=whatever))</code> then I get unused argument fail. If I DO, but don't specify it in the call because grids doesn't exist and I don't want to use it, I get match error, grids missing no default.</p>
  
  <p>How do I get around this? Maybe list it in the function variables list as <code>grids="NULL"</code>, then rather than <code>if(exists("grids"))</code> do <code>if(grids!="NULL")</code></p>
  
  <p>I still don't know why the original match problem is happening though. Match is from the expvarnames/grids names checker, which is AFTER <code>if(exists("grids"))</code> which evaluates to FALSE. WAaaaaaaiiiiittttt..... If I specify grids in the function variables list, i.e. simply putting <code>function(x,grids,etc){do stuff}</code>, does that mean the function CREATES an object called grids, within its environment?
  Man this is so f'd up....</p>
  
  <pre><code>testfun &lt;- function(x,grids)
  {if(exists("grids")) globalgrids&lt;&lt;-grids
  print(x+1)}
  testfun(1) # Error in testfun(1) : argument "grids" is missing, with no default
  
  testfun &lt;- function(x,grids)
  {if(exists("grids")) a&lt;&lt;-c(1,2,3)
    print(x+1)}
  testfun(1) #2 (and globally assigns a)
  </code></pre>
  
  <p>So in the first example, the function seems to have created an object called "grids" because exists("grids") evaluates to true. But THEN, ON THE SAME LINE, when asked to do something with grids, it says it doesn't exist! Schroedinger's object?!
  This is proven in example 2: grids evaluates true and a is globally assigned then the function does its thing. Madness. Complete madness. Does anyone know WHY this ridiculousness is going on? And is the best solution to use my grids="NULL" default in the functions variables list?
  Thanks.</p>
  
  <p>Reproducible example, if you want to but I've already done it for every permutation:</p>
  
  <pre><code>testfun &lt;- function(x,grids)
  {if(exists("grids")) if(!all(expvarnames %in% names(grids))) {stop("Not all expvar column names found as column names in grids")}
    print(x+1)}
  testfun(1)
  testfun(x=1,grids=grids)
  grids&lt;-data.frame(c(1,2,3),c(1,2,3),c(1,2,3))
  expvarnames &lt;- c("a","b","c")
  colnames(grids) &lt;- c("a","b","c")
  </code></pre>