title: Dealing with symbol resolution properly in macros
body: <p>Say I want to make a Clojure macro that does the following:</p>
  
  <pre><code>If x is a list calling the function "bar"
    return :foobar
  else
    return x as a string
  </code></pre>
  
  <p>However, <code>bar</code> is not defined; rather, it is only used internally in the macro, like so:</p>
  
  <pre><code>(foo (bar))
  :foobar
  
  (foo 1)
  "1"
  </code></pre>
  
  <p>One could do something like this:</p>
  
  <pre><code>(defmacro foo [x] 
    (if (and (coll? x) (= (first x) 'bar)) 
        :foobar 
        (str x)))
  </code></pre>
  
  <p>This works great for the <code>(bar)</code> case, as well as for literals. However, symbols do not work as intended, giving the symbol name instead of its associated value:</p>
  
  <pre><code>user=&gt; (def y 2)
  #'user/y
  user=&gt; (foo y)
  "y"
  </code></pre>
  
  <p>One could call the <code>eval</code> function on <code>x</code> before passing it to <code>str</code>, but this causes problem when using the function in <code>let</code>:</p>
  
  <pre><code>user=&gt; (let [a 3 b (foo a)] b)
  java.lang.UnsupportedOperationException: Can't eval locals (NO_SOURCE_FILE:89)
  </code></pre>
  
  <p>Presumably, the problem has to do with symbol resolution, so maybe we try to work something out with syntax-quote:</p>
  
  <pre><code>(defmacro foo [x] 
    `(if (and (coll? '~x) (= (first '~x) '~'bar)) 
      :foobar 
      (str ~x)))
  </code></pre>
  
  <p>Now, the problem is with <code>(foo (bar))</code>, as this expands the else clause to <code>(clojure.core/str (bar))</code>, which throws an exception, as <code>bar</code> is not defined. I then tried doing some shenanigans with <code>eval</code>:</p>
  
  <pre><code>(defmacro foo [x] 
    `(if (and (coll? '~x) (= (first '~x) '~'bar)) 
      :foobar 
      (eval '(str ~x))))
  </code></pre>
  
  <p>But this doesn't work with <code>let</code> bindings again:</p>
  
  <pre><code>user=&gt; (let [a 1 b (foo a)] b)
  java.lang.Exception: Unable to resolve symbol: a in this context (NO_SOURCE_FILE:153)
  </code></pre>
  
  <p>So I'm really at a loss here. It seems as though fixing one problem breaks another. Is there a better, simpler way of making this macro such that it works in the following cases:</p>
  
  <ul>
  <li>In <code>let</code> bindings</li>
  <li>With <code>(bar)</code></li>
  <li>With symbols</li>
  </ul>
  
  <p>P.S. If anybody is curious as to <em>why</em> I want to do this, I'm working on a DSL for Yahoo's YQL service and I want to be able to do things like <code>(select (table :t) ...)</code>, but I need to be able to pass in symbols, as well as literals.</p>