partial vs anonymous function?

264 views
Skip to first unread message

David McNeil

unread,
Apr 14, 2011, 9:46:34 AM4/14/11
to Clojure
I am puzzled by the results below. Can anyone explain the difference
in behavior?

-David

----

(defn mapper [f stream]
`(map ~f ~stream))

(eval (mapper #(+ 1 %) [10 11 12]))
;; -> (11 12 13)

(eval (mapper (partial + 1) [10 11 12]))
;; -> No matching ctor found for class clojure.core$partial...

Mark Rathwell

unread,
Apr 14, 2011, 9:52:16 AM4/14/11
to clo...@googlegroups.com
Try this:

(eval (mapper `(partial + 1) [10 11 12]))


--
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
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
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

David McNeil

unread,
Apr 14, 2011, 9:58:26 AM4/14/11
to Clojure
Mark - Thanks. I am able to permute it to make it work. However, I
cannot explain why the original code fails.

-David

Mark Rathwell

unread,
Apr 14, 2011, 10:17:07 AM4/14/11
to clo...@googlegroups.com

I think it has to do with partial's use of apply, but you would need someone smarter than me to tell you for sure ;)



--

Mark Rathwell

unread,
Apr 14, 2011, 10:42:13 AM4/14/11
to clo...@googlegroups.com

Actually, that doesn't seem to be the case, seems to have something to do with the closure affecting macro expansion, but again, need someone smarter to explain:

user> (defn plus-x [x] (fn [y] (+ x y)))
#'user/plus-x

user> (eval (mapper (plus-x 1) [1 2 3]))
; Evaluation aborted.

user> (eval (mapper (fn [x] (+ 1 x)) [1 2 3]))
(2 3 4)

Ken Wesson

unread,
Apr 14, 2011, 11:38:13 AM4/14/11
to clo...@googlegroups.com
On Thu, Apr 14, 2011 at 10:42 AM, Mark Rathwell <mark.r...@gmail.com> wrote:
>
> Actually, that doesn't seem to be the case, seems to have something to do
> with the closure affecting macro expansion, but again, need someone smarter
> to explain:
> user> (defn plus-x [x] (fn [y] (+ x y)))
> #'user/plus-x
> user> (eval (mapper (plus-x 1) [1 2 3]))
> ; Evaluation aborted.
> user> (eval (mapper (fn [x] (+ 1 x)) [1 2 3]))
> (2 3 4)

This is that weird bug/glitch/unsupported feature when an actual
function object (as opposed to a symbol referring to a local or a var
holding one) is eval'd. It seems that this works for non-closure fns
but fails when the fn closes over a value from its context. I assume
that eval of sexps with embedded function objects is not supported,
and that it works even for some function objects is more or less
accidental.

Embed the quoted function code, e.g. (mapper `(partial + ~x) ...)
rather than (mapper (partial + x) ...), or make a defn out of the
function and call it by name, e.g. (defn foo ...) ... (mapper foo
...).

Note that the former only works if x is something eval'able itself,
such as a number or a string or something similar, or a Clojure data
structure composed ultimately of same. If it is, or contains, some
other kind of Java object, you've got trouble again.

The problem with generic objects in eval is partially solvable:

1. If the sexp is constructed and then eval'd in the same session, a
constant reference to the object could simply be embedded in the
generated bytecode as a class constant of reference type.

2. If the code is being AOT compiled, and the object implements
Serializable, it could be serialized as some sort of resource, and the
AOT output could include a static initializer that loads that resource
and stores a reference in a class constant.

Currently, neither of the above is implemented. The case that would
remain if they were would be:

3. The code is being AOT compiled and the object does not implement
Serializable.

That case subdivides as follows:

3a. The object cannot even in principle usefully be preserved across
sessions or moved between JVMs, e.g. because it contains file handles
or other native resources (ex.: FileInputStream).

3b. The object can in principle be preserved, and fairly simply; case
2 above would Just Work(tm) if you just slapped "implements
Serializable" on the thing's class.

3c. The object can in principle be preserved, but not simply; e.g.
WeakReference, which hooks into the GC; you'd need to first preserve
the referent (if not null) and then a) load that and then b) construct
a WeakReference to it in the target JVM instance. ReferenceQueues add
more complication in that instance. 3c could reduce to 3b in the case
of a proper writeObject/readResolve method pair.

However, for Clojure to support case 3b requires some kind of heap
introspection capability (likely involving native code) that allows it
to directly copy the bytes of an object's in-memory representation.
That prevents making 3c work via the writeObject/readResolve method,
and would presumably not work in sandboxed JVMs. I doubt it's
particularly practical to attempt to support case 3, just 1 and 2.

Armando Blancas

unread,
Apr 14, 2011, 12:26:09 PM4/14/11
to Clojure
I wonder in which cases this code is a good choice: a function that
returns uneval'ed code. Something about macros not being an option
where a function is expected, or a kind of lazy eval? Will this be any
better or worse: (defn m [f s] (fn [] (map f s))) then doing (foo)
instead of (eval foo)?

David McNeil

unread,
Apr 14, 2011, 12:34:45 PM4/14/11
to Clojure
> Will this be any
> better or worse: (defn m [f s] (fn [] (map f s))) then doing (foo)
> instead of (eval foo)?

Armando - Generally I agree that the "m" function you defined is
clearly preferred over a solution based on eval. However, this is a
special case (too much to relate) where I needed a function to produce
an s-expression.

Thanks.
-David

Armando Blancas

unread,
Apr 14, 2011, 1:02:50 PM4/14/11
to Clojure
I copy that. FWIW, I'm not in the eval-is-evil camp, so didn't have an
opinion one way or the other. I've seen code like that in posted
samples and wanted to know if that's a technique useful to have
around.

Ken Wesson

unread,
Apr 14, 2011, 1:06:32 PM4/14/11
to clo...@googlegroups.com
On Thu, Apr 14, 2011 at 12:26 PM, Armando Blancas
<armando...@yahoo.com> wrote:
> I wonder in which cases this code is a good choice: a function that
> returns uneval'ed code. Something about macros not being an option
> where a function is expected, or a kind of lazy eval? Will this be any
> better or worse: (defn m [f s] (fn [] (map f s))) then doing (foo)
> instead of (eval foo)?

It is quite common to write functions that return sexps to simplify
writing macros; macros can call other functions to build parts of
their output.

The OP may also have been debugging a macro and reduced his problem to
a simple, reproducible example using such a function to generate the
problem part of the macro output and eval to trigger it.

There are also cases where eval is needed at run-time, such as dynamic
on-the-fly runtime function creation. Some of the most sophisticated
optimizations involve exploiting patterns in the input not discovered
until runtime, or compiling on the fly a version of an algorithm
specialized to a particular input; e.g. if you're going to try to
factor a big number, you might have code actually generate and compile
code to search for a factor for *that specific* number and then
execute it, and it might run faster than if that number were an
in-theory variable in the code, especially if the algorithm can be
changed depending on properties of the number.

Armando Blancas

unread,
Apr 14, 2011, 1:57:56 PM4/14/11
to Clojure
Interesting. Thanks for your response.

On Apr 14, 10:06 am, Ken Wesson <kwess...@gmail.com> wrote:
> On Thu, Apr 14, 2011 at 12:26 PM, Armando Blancas
>

David McNeil

unread,
Apr 16, 2011, 10:25:48 AM4/16/11
to Clojure
For those who duck it in the future, there is more discussion here:
http://groups.google.com/group/clojure-dev/browse_thread/thread/f4907ebca8ef6e11

-David
Reply all
Reply to author
Forward
0 new messages