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 <matv...@gmail.com> 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 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 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+unsubscr...@googlegroups.com. > 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.