Inlining lets the compiler substitute an alternative implementation at a direct var invocation. A var’s :inline metadata supplies that implementation; :inline-arities can limit which argument counts use it. Where inlining applies, it takes precedence over a thread binding or root binding. A call at an unsupported arity uses the ordinary binding instead. section 16.0
Use definline when a function’s inline form is effectively its body: it defines the function and attaches an :inline implementation without writing both separately. Its declaration needs at least a parameter vector, as in (definline f [] ...); (definline f) is invalid. The form returns a var. Direct calls can expand like macros, but passing the function to a higher-order operation uses it as an ordinary function. section 4.5
(definline sq [x] ; #1 `(let [x# ~x] (* x# x#))) (defn direct-use [x] ; #2 (sq x)) (defn higher-order-use [xs] ; #3 (map sq xs)) (direct-use 2.0) ;; 4.0 (first (higher-order-use [2.0])) ;; 4.0
Compare (sq x) with (map sq xs). The direct call uses the inline form, whose generated local binding evaluates x once; map receives the function value. section 4.5
(ns math-lib-client (:require [math-lib :as m])) (defn vsum [x xs] (map #(m/plus (int x) (int %)) xs)) (vsum 3 [1 2 3]) ; #1 ;; int plus(int int) ;; int plus(int int) ;; int plus(int int) ;; (4 5 6)
Java interop is a practical reason to inline. With plus defined by definline, calls using (int x) and (int %) select IntegerMath/plus(int, int); the ordinary function wrapper in the earlier example selected the Object overload even with those conversions at the call site. section 4.5
Keep the ordinary function and inline form consistent: an inline-only change can make direct and higher-order calls return different results. definline remains marked experimental as of Clojure 1.10; versions before 1.6.0 had a serious AOT-compilation issue. section 4.5



