Hi. Yes, the (eval `(meta ~name)) did the trick, it also seems to be working the way I would like it to in terms of namespaces, which is great! I must confess that I don't fully grok why it has to be that way (syntax-quote plus syntax escape plus eval), but I will just have learn more and hopefully I some day I will ;d Maybe this can be written easier, but this is good enough for me now. Thank you again, you've been of great help.
As for the meta for vars or objects, check this out: user=> (def ^:var-meta testtest ^:obj-meta {:fn "wujek"}) #'user/testtest user=> (meta testtest) {:obj-meta true} user=> (meta (var testtest)) {:ns #<Namespace user>, :name testtest, :var-meta true, :line 1, :file "NO_SOURCE_PATH"} So the metas are different. You said yourself that only IMetas are supported as meta targets, which can be shown here: user=> (def ^:var-meta testtest2 ^:obj-meta 17) #<IllegalArgumentException java.lang.IllegalArgumentException: Metadata can only be applied to IMetas> If metas were always applied to vars, there would be no difference as I guess all vars can habe metadata. wujek On Mon, Jan 14, 2013 at 5:28 PM, Jim foo.bar <jimpil1...@gmail.com> wrote: > aaa ok now I understand what you mean....I'm really sorry but I hadn't > read all your original questions. So lets set things straight: > > > 1. should I attach the meta to the object, or to its var? or maybe I > shouldn't do it at all, and just omit such checks altogether? (but I would > still like to know how to make it work ;d) > > meta-data are always attached on the var if I'm not mistaken... > > > 2. how do I retrieve the meta of an object that is specified by a symbol > passed to a macro by the user? > > the general answer here is that you use ~ inside a syntax-quote to jump > right out of the quoting which results in evaluating the expression. If > you're not in a syntax-quoted form then I can only think of 'eval' which > will resolve the var anyway... > > > 4. in the exception above, the symbol is resolved to the > clojure.core/name, which is wrong as well; I know I can change the symbol > name, but I have the feeling that this is not the way to go ;d > > I'm not sure how to answer this...I know what t do inside the macro to > avoid symbol capturing but I'm not sure what to do in the actual parameter > list of the macro... > > > So, with all these in place I'd say you're looking for something like this: > > (defmacro with-obj [ob] > (if-let [obj-meta (eval `(meta ~ob))] (println "nice") > > (throw (IllegalArgumentException. (str ob " seems not be our > object"))))) > > > Let's see how it works: > > user=> (def my-name "JIM") > #'user/my-name > user=> (defrecord NAME [^String s]) > user.NAME > user=> (def your-name (NAME. "Wujek" {:surname "Srujek"} nil)) ;;your-name > has meta-data > #'user/your-name > user=> (macroexpand '(with-obj my-name)) > IllegalArgumentException my-name seems not be our object user/with-obj > (NO_SOURCE_FILE:4) > user=> (macroexpand '(with-obj your-name)) > nice > nil > > I think we 're getting there yes? Is this more helpful? > > Jim > > > > > On 14/01/13 15:46, Wujek Srujek wrote: > > When I invoke a macro: > (with-object someobject) > someobject is not evaluated, it is passed as a symbol to the macro. I need > somehow to get the meta for the object that is hidden behind that symbol. > So, I won't be passing objects in-line, as you did in your Foo example, I > will first be doing: > (defobject foo {map of my functions / values}) > (with-object foo (some-expressions)) > > Throwing an exception when meta is not there is one thing what I want > (the missing part); the printing was just there to make the example > shorter, it's not actually the real code - I don't need a macro for that. > In reality, after all checks, there is code generated that desctructures > the map in a (let) and executes some-expressions in this context, making > certain bindings available for the expressions. This bit works fine, it's > just the meta check that doesn't work as I don't know how to get the object > that the symbol points to (in the macro, all I have is just a symbol): > > user=> (def somename 17) > #'user/somename > user=> (defmacro testabc [name] (class name)) > #'user/testabc > user=> (testabc somename) > clojure.lang.Symbol > > When I change the macro like this: > user=> (defmacro testabc [name] name) > > the object is returned: > user=> (testabc somename) > 17 > > but it is because after macro expansion the returned symbol resolves to > the object I set before. I would like to be able to get access to that > object at macro call time. > But when I come to think about it now, I guess this would be impossible? > Are the vars available when the macro is called? i.e.: > > user=> (def somename 17) > user=> (testabc somename) ; <- in this macro, I need to take the > 'somename' symbol and retrieve value 17 from above - is this possible at > all? > > Thanks for your help, > wujek > > > On Mon, Jan 14, 2013 at 4:25 PM, Jim foo.bar <jimpil1...@gmail.com> wrote: > >> I am not sure I follow...Do you by any chance want the macro-expansion >> to lead you directly to one of your two options (printing or exception)? In >> this case you can do this: >> >> (defmacro with-obj [ob] >> (if-let [obj-meta (meta ob)] (eval ob) ;not replacing any code but >> eval-ing on the fly >> >> (throw (IllegalArgumentException. (str ob " seems not be our >> object"))))) >> >> (defrecord Foo [a b]) >> >> user=> (macroexpand '(with-obj "Jim")) >> IllegalArgumentException Jim seems not be our object user/with-obj >> (NO_SOURCE_FILE:3) >> user=> (macroexpand '(with-obj (with-meta (Foo. 'x 'y) {:t 1 :p 2}))) >> #user.Foo{:a x, :b y} >> >> So now you get the exception or the actual object at macro-expansion >> time...Does that help at all? >> >> Jim >> >> >> >> On 14/01/13 14:56, Wujek Srujek wrote: >> >> Actually, the with-object mecro is very similar to >> clojure.algo.monads/with-monad - it also lets a few bindings, like m-bind >> or m-result, and executes user-defined expressions in the context of the >> monad specified by a name. They just don't perform such checks, you can >> call with-monad with any symbol, and you will get an NPE: >> user=> (require '[clojure.algo.monads :refer :all]) >> user=> (domonad identity-m [a 2 b 3] (* a b)) >> 6 >> user=> (domonad whatever [a 2 b 3] (* a b)) >> NullPointerException user/eval1803 (NO_SOURCE_FILE:1) >> >> That's probably because the monad functions set up by with-monad are >> nils. (domonad uses with-monad under the hood.) If I perform my check, I >> will be able to give a much nicer error message, and there is a lot value >> in that. >> >> wujek >> >> >> On Mon, Jan 14, 2013 at 3:45 PM, Wujek Srujek <wujek.sru...@gmail.com>wrote: >> >>> Because this is not the whole functionality ;d The check is just a >>> fragment, the one that doesn't work. There is much more to it, like taking >>> the object, taking some keys and values and using them in (let) and then >>> executing some code in this context (which is another parameter, which is >>> not in my example as I wanted to keep it simple). >>> If I could do it with a function, I would of course prefer it, but I am >>> not sure if it can work. >>> >>> wujek >>> >>> >>> On Mon, Jan 14, 2013 at 3:41 PM, Jim foo.bar <jimpil1...@gmail.com>wrote: >>> >>>> Why does this have to be a macro? Why can't it be a first-class >>>> function instead? >>>> >>>> (defn with-obj [ob] >>>> (if-let [obj-meta (meta ob)] name >>>> (throw (IllegalArgumentException. (str ob " seems not be our >>>> object"))))) >>>> >>>> Jim >>>> >>>> >>>> >>>> On 14/01/13 14:34, Jim foo.bar wrote: >>>> >>>>> Of course you should know that built-in java types do not support >>>>> meta-data...You need to implement IObj in order to provide meta-data >>>>> support to your own types...otherwise use records... >>>>> >>>>> Jim >>>>> >>>>> >>>>> On 14/01/13 14:32, Jim foo.bar wrote: >>>>> >>>>>> On 14/01/13 14:27, wujek.sru...@gmail.com wrote: >>>>>> >>>>>>> (defmacro with-obj [name] >>>>>>> (let [obj-meta (meta name)] >>>>>>> (if (or (nil? obj-meta)) ; (not (::my-obj obj-meta))) >>>>>>> (throw (IllegalArgumentException. (str name " seems not be our >>>>>>> object"))))) >>>>>>> `(println "nice")) >>>>>>> >>>>>>> >>>>>> >>>>>> Try this: >>>>>> >>>>>> >>>>>> (defmacro with-obj [name] >>>>>> `(if-let [obj-meta# (meta ~name)] >>>>>> (println "nice") >>>>>> (throw (IllegalArgumentException. (str ~name " seems not be our >>>>>> object"))))) >>>>>> >>>>>> HTH... >>>>>> >>>>>> Jim >>>>>> >>>>>> >>>>>> >>>>> >>>> -- >>>> 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 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 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 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 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 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