Fork me on GitHub

Is there a (fast) way to apply but with the second to last argument expanded instead of the last?


Arguments after the first (the function) are added to the list of args anyway? Do you have an example snippet?


@UHK8B8STX: I want to do something like

(defn foo [& xs] (apply' str \< xs \>))
such that (= (foo 1 2 3) "<123>")


I could do something like

(defn foo [& xs] (str (apply str \< xs) \>))
(defn foo [& xs] (str \< (clojure.string/join xs) \>)
…but I don’t want to allocate any temporary strings


Likewise I could do something like

(defn foo [& xs] (apply str (concat [\<] xs [\>])))
but that seems like it’d be inefficient as well


have you checked out format or cl-format?


you can also use backtick-quoting and un-splice


(defn foo [& xs]
  (apply str `(\< [email protected] \>)))

(foo 1 2 3)
;; => "<123>"


cl-format takes a stream argument which it can output to, which I'd have to check, but might let you avoid unnecessary string creation


I’ve looked at format but not cl-format


Format doesn’t work AFAICT since I’d have to generate the format string


…but the backtick solution seems like it should work (as long as it’s performant enough)! thx


I’d use your early suggestion, but just passing the opening char (not that this is a big deal):

(defn foo [& xs] (apply str \< (concat xs [\>])))
Why? Because the apply function just uses clojure.lang.AFn/applyTo and that is going to do the work of getting through the final seqable argument no matter how you handle it. Splicing doesn’t change that. The str function then does a recur to run down that seq and append to a string buffer.


The setup of creating a lazy concat to pick up the final element to go on the end is relatively small, and not going to be a noticeable cost.


If you have a performance issue with that (and I’d be surprised if you did!) then you can just pull apart the str implementation and append to the StringBuilder yourself, but I’d be really surprised if you gained any benefit from doing that


cool, thanks for the insight @U051N6TTC!

👍 3

When you’re looking to minimize work like that, then the results can be counter-intuitive. It’s worth trying a few million executions of the code in question and timing it. At that point, if you’re unhappy, then it’s worth looking into how it works and see if there is anything redundant happening. (I like to look anyway, just to find out how it works)


If you try (source apply) you’ll see how it uses the IFn method applyTo. That’s at You’ll see that for anything more than 20 values, it creates an array of the data to pass in, and the function should be handling an array parameter by that point anyway. So what you’re passing will go to an array. Doesn’t seem too bad. Hows does str manage all these parameters? (source str) does this in its final arity:

((fn [^StringBuilder sb more]
          (if more
            (recur (. sb  (append (str (first more)))) (next more))
            (str sb)))
      (new StringBuilder (str x)) ys)
So it just iterates along and uses java.lang.StringBuilder.append(String s) on every element


This is one of the things I like about Clojure. It’s very easy to see what’s actually going on


Inspired by quoll, I looked up what the backtick version expands to:

(apply str (clojure.core/seq (clojure.core/concat (clojure.core/list \<) xs (clojure.core/list \>))))


I have a problem with next-jdbc... It suddenly refuses to work properly. No code changes have been made. Reading from the database works fine. But as soon as I use with-transaction or call a hugsql generated function that would end in a write, I get an

Execution error (ConnectException) at (
Connection refused (Connection refused)
exception. The role definitely does have write rights from my machine, it is the role I use daily to make changes to the database. Anyone knows what that could be?


might want to ask in #sql


hello, in CLJS there is the IFind protocol to define how a type should respond to find, is there an analogous one in CLJ?

Alex Miller (Clojure team)16:08:13

not really. probably the closest is Associative's entryAt() method

Alex Miller (Clojure team)16:08:00

if a type implements Associative, that method will be used

Alex Miller (Clojure team)16:08:54

(but there are also special cases in RT.find() for Map and ITransientAssociative2)


I remember some advice that if is a namespace, then should not be a namespace. does anyone know where I might have read this?

Alex Miller (Clojure team)18:08:12

not an issue at all in clojure (and pretty common) but I think there is some issue with this in cljs?


pretty sure thats only CLJS-only advice since can clash with


so namespaces are reified into the same "namespace" as the definitions in them? that's weird


I guess that's using js globals, and that's simply the semantics offered?


yeah clojurescript reifies namespaces as objects & properties on objects


too late to change it to something else 😉


yeah, plus it has some nice things about it. using closures as namespaces has its own problems…


that solves my mystery! thank you


nah I'd still have used the same system. just probably would have been better not nested. eg. (ns (defn bar ...) becomes ns$app$ or so


ah yes that would be better