This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # announcements (5)
- # babashka (1)
- # beginners (193)
- # calva (79)
- # cider (18)
- # clara (4)
- # clojure (38)
- # clojure-europe (12)
- # clojure-france (8)
- # clojure-nl (12)
- # clojure-sweden (1)
- # clojure-uk (50)
- # clojurescript (37)
- # conjure (30)
- # cursive (3)
- # data-science (2)
- # datalog (7)
- # datomic (12)
- # events (2)
- # expound (3)
- # figwheel-main (1)
- # fulcro (45)
- # graalvm (1)
- # jobs (1)
- # jobs-discuss (11)
- # luminus (1)
- # malli (5)
- # off-topic (32)
- # reagent (6)
- # reitit (32)
- # shadow-cljs (25)
- # spacemacs (2)
- # sql (22)
- # vim (6)
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?
@: I want to do something like
(defn foo [& xs] (apply' str \< xs \>))
(= (foo 1 2 3) "<123>")
I could do something like
(defn foo [& xs] (str (apply str \< xs) \>))
…but I don’t want to allocate any temporary strings
(defn foo [& xs] (str \< (clojure.string/join xs) \>)
Likewise I could do something like
but that seems like it’d be inefficient as well
(defn foo [& xs] (apply str (concat [\<] xs [\>])))
(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
…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):
Why? Because the
(defn foo [& xs] (apply str \< (concat xs [\>])))
applyfunction just uses
clojure.lang.AFn/applyToand 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
strfunction then does a
recurto 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
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
applyTo. That’s at https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/AFn.java#L143
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.
str manage all these parameters?
(source str) does this in its final arity:
So it just iterates along and uses
((fn [^StringBuilder sb more] (if more (recur (. sb (append (str (first more)))) (next more)) (str sb))) (new StringBuilder (str x)) ys)
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
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?
Execution error (ConnectException) at java.net.PlainSocketImpl/socketConnect (PlainSocketImpl.java:-2). Connection refused (Connection refused)
hello, in CLJS there is the
IFind protocol to define how a type should respond to
find, is there an analogous one in CLJ?
(but there are also special cases in RT.find() for Map and ITransientAssociative2)
I remember some advice that if
app.foo.bar is a namespace, then
app.foo should not be a namespace. does anyone know where I might have read this?
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
app.foo/bar can clash with
so namespaces are reified into the same "namespace" as the definitions in them? that's weird
yeah, plus it has some nice things about it. using closures as namespaces has its own problems…
nah I'd still have used the same system. just probably would have been better not nested. eg.
(ns app.foo) (defn bar ...) becomes
ns$app$foo.bar or so