title: DSL syntax with optional parameters
body: <p>I'm trying to handle following DSL:</p>
  
  <pre><code>(simple-query 
    (is :category "car/audi/80")
    (is :price 15000))
  </code></pre>
  
  <p>that went quite smooth, so I added one more thing - options passed to the query:</p>
  
  <pre><code>(simple-query {:page 1 :limit 100}
    (is :category "car/audi/80")
    (is :price 15000))
  </code></pre>
  
  <p>and now I have a problem how to handle this case in most civilized way. as you can see <code>simple-query</code> may get hash-map as a first element (followed by long list of criteria) or may have no hash-mapped options at all. moreover, I would like to have <em>defaults</em> as a default set of options in case when some (or all) of them are not provided explicite in query.</p>
  
  <p>this is what I figured out:</p>
  
  <pre><code>(def ^{:dynamic true} *defaults* {:page 1 
                                    :limit 50})
  
  (defn simple-query [&amp; body]
    (let [opts (first body) 
          [params criteria] (if (map? opts) 
                               [(merge *defaults* opts) (rest body)]
                               [*defaults* body])]
         (execute-query params criteria)))
  </code></pre>
  
  <p>I feel it's kind of messy. any idea how to simplify this construction?</p>