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

Reply via email to