I haven't taken the time to fully grok your macro, but the error is not the 
fault of your macro, but of the function invocation. (foo x) is causing the 
error because x is undefined. foo is a plain function, not a macro, so it 
tries to evaluate each argument. (foo 'x) works fine for me, as does (let 
[x 42] (foo x))

I guess the fact that (foo x) recycled the name of the parameter used in 
the function definition is what made the error message confusing?

On Monday, July 21, 2014 9:49:10 AM UTC-7, Dave Tenny wrote:
>
> In my case, I'm trying to use a the expression '[x] that is available to 
> the macro in the resulting product.  So I don't want the value of x at all, 
> just a vector with the symbol x.
>
> That vector is in a variable I have in the macro named 
> 'positional-parameters', so I substitute '~positional-parameters to with 
> the hope of getting '[x] in the resulting definition.
>
> Here's a fragment of the overall defs.  As you can see I'm just messing 
> around, I was trying to write a defun with 'supplied-p' lambda list 
> semantics, and my clojure/macrology is awful.  It's the macro near the 
> bottom.  You can append this to 
> https://github.com/dtenny/clojdt/blob/master/src/jdt/cl.clj if you want 
> to git clone and compile it.
>
> (def lambda-list-keyword-symbols
>   "Symbols without namespace specifications"
>   (into #{} (map symbol ["&allow-other-keys" "&key" "&rest" "&aux" 
> "&optional"])))
>
> (defn lambda-list-keyword?
>   "If x is a lambda list keyword, in any case, return the canonicalized 
> form as a symbol.
>    If it starts with an ampersand but is not a valid lambda list keyword, 
> throw an exception."
>   [x]
>   (let [sym-name (.toLowerCase (name x))]
>     (if (= (first sym-name) \&)
>       (if-let [lambda-sym (lambda-list-keyword-symbols (symbol sym-name))]
>         lambda-sym
>         (throw (Exception. (str "'" x "' is not a valid lambda list 
> keyword."))))
>       nil)))
>
> (defn lambda-list-segment
>   "Return three values in a vector.
>
>    The first value is a vector of non-lambda-list-keywords
>    in l before the next lambda list keyword in the list.  Order is 
> preserved.
>
>    The second value is the canonicalized lambda list keyword (as a clojure 
> symbol, e.g. '&aux)
>    that terminated accumulation, or nil if we reached the end of the list.
>
>    The third value is the rest of the list following the lambda list 
> keyword, or nil if there aren't
>    any more values.
>
>    E.g. (lambda-list-segment '(a b &optional c))
>         => [[a b] &optional (c)]"
>   [l]
>   (loop [result [] l l]
>     (if (empty? l)
>       [result nil nil]
>       (let [head (first l)
>             tail (rest l)
>             lambda-keyword (lambda-list-keyword? head)]
>         (if lambda-keyword
>           [result lambda-keyword tail]
>           (recur (conj result head) tail))))))
>
> (defn partition-lambda-list
>   "Return a map keyed by lambda list keyword (or the pseudo keyword 
> '&positional'
>    for positional args), and valued by a vector lambda vars associated 
> with the
>    type of lambda list element, in the order specified by the caller.
>    E.g. (partition-lambda-list [a b c &optional (d nil d-supplied-p) &key 
> e])
>         => {&positional [a b c] &optional [(d nil d-supplied-p)] &key [e]}
>    Ignore case in things appearing to be lambda list keywords.
>    Complain if any symbol begins with an ampersand and is not a valid 
> lambda list keyword.
>    Preserve order of parameters."
>   [lambda-list]
>   (let [first-chunk (lambda-list-segment lambda-list)
>         positionals (first first-chunk)]
>     (loop [result {'&positional positionals}
>            next-lambda-key (second first-chunk)
>            lambda-list (nth first-chunk 2)]
>       (if (empty? lambda-list)
>         (if next-lambda-key
>           (merge result {next-lambda-key []}) ; in case it's 
> &allow-other-keys
>           result)
>         (let [chunk (lambda-list-segment lambda-list)]
>           (recur (merge result {next-lambda-key (first chunk)})
>                  (second chunk)
>                  (nth chunk 2)))))))
>
> (defn parse-defun-decls
>   "Parse defun elements following the lambda list.
>    If there are declarations, strip them from the sequence.
>    Return a vector of two things.
>    1) the docstring, or nil if there isn't one.
>    2) forms following the optional declarations and docstring, nil if 
> there aren't any."
>   [s]
>   (let [declare? (fn [l]
>                    (and (list? l)
>                         (.equalsIgnoreCase (name (first l)) "declare")))]
>     (loop [s s]
>       (if (empty? s)
>         [nil nil]
>         (let [head (first s)]
>           (cond (string? head) [head (rest s)] ; **BUG** won't work if 
> declare is after docstring
>                 (declare? head) (recur (rest s))
>                 :else [nil s]))))))
>
> (defn positional-values 
>   "Given a sequence of formal parameter names for positional values
>    and a sequence of actual arguments to a defun'ed function call,
>    return a vector of values from actual args to be bound to parameters.
>    Return [] if there aren't any."
>   [parameters actual-args]
>   (if parameters
>     (if (< (count actual-args) (count parameters))
>       (throw (Exception. (str "Insufficient arguments in " actual-args
>                               " to match positional parameters in " 
> parameters)))
>       (loop [values [] args actual-args]
>         (if (empty? args)
>           values
>           (recur (conj values (first args)) (rest args)))))
>     []))
>
> ;; *FINISH*: define/support RETURN-FROM
>
> (defmacro defun
>   "defun function-name lambda-list [[declaration* | documentation]] form*
>    => function-name
>    Arguments and Values:
>     function-name---a function name.
>     lambda-list---an ordinary lambda list.
>     declaration---a declare expression that is discarded.
>     documentation---a string; not evaluated.
>     forms---an implicit progn.
>
>    Notes:
>      This is meant to be as common-lisp oriented as possible in a clojure 
> environment. 
>      Thus a function definition is (defun foo (&optional bar) ...)
>      and NOT                       (defun foo [clojure-y args] ...)"
>   [function-name lambda-list & decls-doc-forms]
>   (let [param-map (partition-lambda-list lambda-list)
>         [docstring forms] (parse-defun-decls decls-doc-forms)
>         args-var (gensym "args")
>         positional-parameters (get param-map '&positional)]
>     (if docstring
>       (comment ; *FINISH* docstring variant
> ;;      `(defn ~function-name ~docstring [& ~args-var]
> ;;         (let [~@(lambda-list-bindings param-map args-var)]
> ;;           ~@forms))
>         )
>       `(defn ~function-name [& ~args-var]
>          ;; *FINISH*: other param types once we get positional values 
> working
>          (let [~positional-parameters (#_positional-values print 
> '~positional-parameters ~args-var)]
>            ~@forms)))))
>
> (println (macroexpand-1 '(defun foo (x) (println x))))
> ;(println (macroexpand '(defun foo (x) (println  x))))
> (defun foo (x) (println x))
> (foo x)  ; <<<---- generates the error
>
>
>
>
>
> On Sun, Jul 20, 2014 at 5:46 PM, Matthew DeVore <mat...@gmail.com 
> <javascript:>> wrote:
>
>> I don't have a Clojure REPL handy at the moment but it looks like the x 
>> symbol is being resolved in the macro context rather than the expansion 
>> context. In the macro source, where you have a plain x, try to replace it 
>> with ~'x ... This blog post may be relevant: 
>> http://amalloy.hubpages.com/hub/Unhygenic-anaphoric-Clojure-macros-for-fun-and-profit
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@googlegroups.com 
>> <javascript:>
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com <javascript:>
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> ---
>> You received this message because you are subscribed to a topic in the 
>> Google Groups "Clojure" group.
>> To unsubscribe from this topic, visit 
>> https://groups.google.com/d/topic/clojure/grxYLrjnz60/unsubscribe.
>> To unsubscribe from this group and all its topics, send an email to 
>> clojure+u...@googlegroups.com <javascript:>.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to