I won't speak directly to your use-case other than saying that `extend` is 
already a function, so there is no reason to call it with a macro or via 
strange evaluation orders via quotes and eval.
You can define the record first, as normal, then call `extend` after 
dynamically and without messing with the evaluation order of functions etc.

I may be missing something more that you were trying to do, but from your 
example I didn't see any need for the complexity.

On the topic of if eval allows arbitrary objects to be embedded in the 
"code" it is evaluating:

I can see how the docs @ http://clojure.org/reference/evaluation could 
mislead someone to thinking that it is perfectly fine and acceptable to 
embed any objects into a call to `eval`, but I really don't think that is 
what the docs are discussing in this case.  Calling `eval` is a way to dig 
into the evaluator of Clojure to use it "ad hoc" yourself at a different 
time than "normal".

So at this point, you've circumvented Clojure's standard evaluation and you 
are attempting to take matters into your own hand.  When you do that, there 
starts to become a lot of subtle issue, like the one of whether or not you 
can get away with embedding already evaluated objects into a new 
evaluation.  Since, in your example, you functions are already evaluated to 
their function objects, you are effectively "double evaluating" them.  When 
you do that, expect issue.

This is a subtle and confusing topic because there are indeed times when 
you can get away with embedding objects into the code you are calling eval 
on.  However, I'd argue that is not the normal case and you shouldn't rely 
on that because it doesn't take much change to break it and no longer be 
able to do it.  For example, functions that have closures, I believe, can 
never successfully be embedded into a call to eval.

The real point here is in understanding evaluation semantics.  The reader 
reads characters/text into data structures.  However these data structure 
are not unbounded.  They are the data structures that are used to describe 
the syntax of the Clojure language, e.g. [], {}, (), :keywords, symbols, 
"strings", 123, etc.
If you try to print a function object, you'll see it has no clear 
representation as a valid data structures in the Clojure syntax subset of 
data structures.  
It'll be something like: <clojure.lang.AFnblah@123>

This is your warning sign that it is going to be trouble to call eval on 
it.  Eval is intended to evaluate _code_ represented as data.  This 
function object is not in a form amendable for interpretation as code.

If you do not try to control evaluation yourself, when evaluating functions 
typically looks like this (fn [x] (inc x)).  That is not a function object 
to the evaluator.  It is a list, with 3 elements.  The first is a symbol, 
the next is a vector, the last is another list, and we can describe its 
subforms similarly.

Clojure does provide a facility to give a meaningful reader/data syntax 
representation to arbitrary objects to allow evaluation later for things 
like serialization.  This is via the 
clojure.core/print-dup family of functionality.  Functions themselves in 
Clojure do not out-of-the-box come with a useful implementation of 
print-dup, but it is a multimethod and can be dynamically extended to new 
types of data.

I think you should try to solve your problem in a simpler way than going to 
this level of depth and/or trying to call eval yourself on 
already-pre-evaluated forms, but for the sake of learning, you may be 
interested in seeing how to make a macro for creating functions that do 
have a print-dup implementation that would allow them to be printed as 
readable, then "evaluatable" code data structures later on. 
 https://github.com/sorenmacbeth/serializable-fn is an example of this.  I 
have used it for inspiration before where I did want to be able to 
serialize pre-eval'ed functions, but I had some tweaks to it of my own. 
 The basic idea holds.  However, I only have needed to go to this level of 
complexity when I was trying to serialize this data so that I could store 
it away and use it in another separate process later, which I think is 
where it can become useful.


Hopefully you find this useful.

On Wednesday, May 4, 2016 at 5:55:12 PM UTC-5, Ben Kovitz wrote:
>
> On May 4, 2016, at 6:08 PM, Johannes <bra...@nordakademie.de <javascript:>> 
> wrote:
>
> okay, but why does the following work without quotation?
> user> (def f- (let [v 1
>               f (fn [x] x)] f))
> ;; => #'user/f-
> user> (eval {:d f-})
> ;; => {:d #function[user/fn--14679/f--14680]}
> user>  
>
>
> The problem is that the place in my program where I give the map 
> containing the function object to eval, the map cannot be quoted.
>
>
> Hmm, I thought I had read “eval doesn’t accept function objects” in a 
> couple places on the Internet, but when I checked this page:
> http://clojure.org/reference/evaluation
> I found the sentence "Any object other than those discussed above will 
> evaluate to itself.” So, it appears to be a bug, either in the 
> documentation or in eval.
>
> I’m only a Clojure noob, having started four weeks ago. so we’ll both have 
> to wait for a more authoritative explanation from someone more familiar 
> with Clojure internals. The reason I know about this (or thought I did) is 
> because I recently struggled with a similar problem: dynamically supplying 
> a method map to extend a protocol to a record. My solution was to define a 
> top-level dynamically rebindable symbol and refer to it inside the 
> expression passed to eval, something like this (untested code):
>
> (def ^:dynamic method-map-holder)
>
> (def dynamic-def-record [record-sym fields-vector method-map]
>   (binding [method-map-holder method-map]
>     (eval `(defrecord ~record-sym ~fields-vector))
>     (eval `(extend ~record-sym
>                    ~'my-project.core/MyProtocol
>                    method-map-holder))))
>
> The trick is to call binding to put the method-map (containing function 
> objects) into a place where eval can see it. That place is: bound to a 
> top-level symbol, which also appears in the object passed to eval. Note 
> that inside the ` form passed to eval, method-map-holder is not preceded 
> by a tilde. eval will see that exact symbol (qualified by the enclosing 
> namespace). The point of all this is to avoid evaluating the map before 
> passing it to eval.
>
> Be aware that the above is an ugly hack, and probably not the best way to 
> do it. I showed my actual code to someone with years of Clojure experience, 
> and he immediately said, “Calling eval is a code smell: there’s almost 
> always a better way to do what you’re trying to do,” and we quickly found a 
> likely way to do what I needed with a macro. However, we did not find a way 
> around temporarily binding the method-map to a dynamically rebindable 
> symbol.
>
> --
> Ben Kovitz
> http://mypage.iu.edu/~bkovitz/
>
>
>

-- 
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