Alex Miller <
al...@puredanger.com> writes:
Hi Alex,
> 2) "like defmacro" is intended to convey that a definline should not
> be expected to work as a HOF. Admittedly, that is subtle. :)
To me, the "like defmacro" conveys that it's syntax is like defmacro.
If definline didn't have the intention of also working as HOF, then it
would be equivalent to defmacro with the exception that it doesn't error
at compile-time (or at least runtime) when the definline-defined
function is used as a HOF. It should have been named
defmacro-with-hiding-of-programmer-errors in that case.
If one shouldn't call a definline function as HOF, then why not change
its definition to?
(defmacro definline
"Experimental - like defmacro, except defines a named function whose
body is the expansion, calls to which may be expanded inline as if
it were a macro. Cannot be used with variadic (&) args."
{:added "1.0"}
[name & decl]
(let [[pre-args [args expr]] (split-with (comp not vector?) decl)]
`(do
(defn ~name ~@pre-args ~args
(throw (RuntimeException. "DON'T CALL A DEFINLINE FN AS HOF!")))
(alter-meta! (var ~name) assoc :inline (fn ~name ~args ~expr))
(var ~name))))
Or make definline an alias for defmacro (if that's possible).
In both cases, calls like (map my-definline coll) would throw at
compile-time and prevent what you consider a misuse.
> The title of CLJ-1227 ticket is "Definline functions do not work as
> higher-order functions when AOT compiled". Per #2, don't do that and
> per #1, at your peril.
The problem is that even when *I* don't use definline (or only use it
non-HOF-y), some of my *dependencies* might do. And in that case, my
library or application will malfunction when it is AOT-compiled, because
AOT-compilation also AOT-compiles all dependencies. And AOT-compilation
is common at least for stand-alone applications and libs that need to be
callable from Java. Oh, and of course for production systems!
And the author of that dependency causing my trouble is not even the
culprit, because the bug only occurs with AOT-compilation, so normal
unit testing with clojure.test won't find it.
> While I appreciate that there is a patch on the ticket, the decision
> in this case was to not spend time on this issue.
Just by answering my mail and comment on the issue, you've already spend
more time on this issue than what would have been required to review and
apply my patch, or to come up with some other solution.
> Rich sees compiler macros as a strictly better solution than definline
> and would prefer to move in that direction for this kind of
> functionality.
I agree with him. Nevertheless, that some feature will eventually be
removed and superseded by something better does not mean that we should
simply ignore the bugs it has.
As said, not stuffing that hole in one way or another is grossly
negligent. More people than Colin and me will get bitten, and they get
bitten even harder when the faulty definline code is not in there own
stuff but somewhere in a dependency. And in both Colin's an my case,
the effect of the issue were not errors but wrong results which are much
harder to debug.
> I don't personally see that changing the word "Experimental" to
> "Deprecated" in the doc string would change anything.
I partly agree, because once you know how a function/macro works, you
don't check the docstring again. However, it might make a little
difference for those that think about using definline right now.
But anyway, IMO just rephrasing the docstring is not enough.
> To me those both mean, you probably shouldn't use this unless you're
> aware of the ramifications.
I'm pretty sure nobody has been aware of the fact that definline behaves
differently in AOT-compiled code than in non-AOT-compiled code.
Bye,
Tassilo