FWIW, it doesn't look like `every?` has any inlining:
=> (with-redefs [every? (constantly 5)]
(every?))
5
The metadata seems to confirm:
=> (meta #'every?)
{:ns #<Namespace clojure.core>, :name every?, :arglists ([pred coll]), :added
"1.0", :static true, :doc "Returns true if (pred x) is logical true for every x
in coll, else\n false.", :line 2359, :file "clojure/core.clj", :tag
java.lang.Boolean}
However, `+` (and all other math ops) do have inlining:
=> (with-redefs [+ (constantly 5)]
(+ 1 1))
2
That fact is surfaced (and driven) by the metadata, which you can check:
=> (meta #'+)
{:ns #<Namespace clojure.core>, :name +, :file "clojure/core.clj", :line 919,
:arglists ([] [x] [x y] [x y & more]), :added "1.2", :inline-arities
#<core$_GT_1_QMARK_ clojure.core$_GT_1_QMARK_@1b78efd8>, :inline
#<core$nary_inline$fn__3566 clojure.core$nary_inline$fn__3566@b74cb21>, :doc
"Returns the sum of nums. (+) returns 0. Does not auto-promote\n longs, will
throw on overflow. See also: +'"}
So you could provide a light wrapper around `with-redefs` to die quickly upon
attempting to redefine such vars.
Alternatively, if you are brave, you can eliminate inlining for a particular
var/fn (or all of them?!?):
=> (alter-meta! #'+ dissoc :inline :inline-arities)
{:ns #<Namespace clojure.core>, :name +, :file "clojure/core.clj", :line 919,
:arglists ([] [x] [x y] [x y & more]), :added "1.2", :doc "Returns the sum of
nums. (+) returns 0. Does not auto-promote\n longs, will throw on overflow.
See also: +'"}
=> (with-redefs [+ (constantly 5)]
(+ 1 1))
5
I'd be very wary about this, insofar as people are (without realizing it)
depending on inlining and other performance mechanisms to get their code
performing as it does today. I'd print a warning about what's going on or
something, anyway.
Cheers,
- Chas
On Nov 1, 2011, at 11:40 AM, Brian Marick wrote:
> Clojure sometimes inlines functions. `every?` is an example. As a result, you
> can have a function that uses `every?`, call it like so:
>
> (with-redefs [every? (fn [& args] (println "Hi mom!") false)]
> (function-that-calls-every))
>
> ... and not get the results that the text of the program calls for.
>
> This behavior with inlined functions has led to something like three
> independent confused messages to the Midje mailing list. I don't relish
> having to explain the issue forevermore. Is it a reasonable enhancement
> request to ask that `with-redefs` blow up when given a function that will be
> inlined? Alternately, could {:will-be-inlined true} be added to the metadata
> of such vars so that tools like Midje can check for themselves?
>
> (My preferred solution would be a way to turn off this and other
> optimizations that change behavior in edge cases, but I believe that's
> already been ruled out.)
>
> -----
> Brian Marick, Artisanal Labrador
> Now working at http://path11.com
> Contract programming in Ruby and Clojure
> Occasional consulting on Agile
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to [email protected]
> Note that posts from new members are moderated - please be patient with your
> first post.
> To unsubscribe from this group, send email to
> [email protected]
> 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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en