This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-11-08
Channels
- # announcements (42)
- # aws (2)
- # babashka (69)
- # beginners (38)
- # calva (18)
- # cider (39)
- # circleci (1)
- # clj-commons (10)
- # cljs-dev (2)
- # clojure (36)
- # clojure-australia (14)
- # clojure-europe (25)
- # clojure-gamedev (40)
- # clojure-losangeles (4)
- # clojure-nl (5)
- # clojure-sweden (1)
- # clojure-uk (5)
- # clojurescript (133)
- # core-logic (24)
- # cursive (7)
- # datalevin (4)
- # datascript (3)
- # figwheel-main (1)
- # fulcro (45)
- # honeysql (1)
- # integrant (43)
- # introduce-yourself (1)
- # jobs (4)
- # leiningen (3)
- # lsp (32)
- # nextjournal (9)
- # pathom (18)
- # polylith (21)
- # portal (65)
- # re-frame (6)
- # releases (1)
- # remote-jobs (1)
- # reveal (12)
- # rewrite-clj (1)
- # sci (84)
- # tools-deps (22)
I would like to print the parameters based on the keyword selector
(defn shcomm [& comm printcommand]
(when (= printcommand :print) (println (apply splitcomm comm)))
(apply sh (apply splitcomm comm)))
and use it like this:
(shcomm "ls " "-a" :print)
The current version doesn't work, obviously, because the comm param. also incorporates :print. What's the right way to do this?There are several ways to accomplish something like this. Generally, we want the "and then some number of things" arguments to be the last argument to use the &
like that. However, if we're going to say "the last thing in that bunch of things is always special and separate", we could use a let block and bind (for example) printcommand to be (last comm)
and then either use a different name or re-bind comm in the let scope as (butlast comm)
. I think it might be more idiomatic, though, to take a list/vector as your comm
value, so the call would end up looking something like (shcomm ["ls" "-a"] :print)
. Alternatively, we could take printcommand as the first argument, and then the & comm
bit would just work:tm: .
I generally prefer an optional option map for these kind of... err... optional options:
(defn- shcomm
[comm & [{:keys [print?]}]]
(apply (if print? println sh) comm))
(shcomm ["ls" "-a"])
(shcomm ["ls" "-a"] {:print? true})
I guess I prefer butlast, was not sure if it's idiomatic, though. Wrapping param in vector makes if heavy and much less fun. So does the optional map
(shcomm "ls -la" :print) and (shcomm "ls -la")
reads much less busy if you have dozens of these lines
What about functions like cheshire.core/parse-string
, it uses the last true parameter to keywordise. How this kind of func are realised?
cheshire.core/parse-string
takes either one, two or three arguments. The first argument is always a single string.
It looks like this
(defn parse-string
([string] (parse-string string nil nil))
([string key-fn] (parse-string string key-fn nil))
([^String string key-fn array-coerce-fn]
(when string ... *THIS IS WHERE PARSING HAPPENS* ))))
This is an example of a multi-arity function: https://clojure.org/guides/learn/functions#_multi_arity_functions
well in my case I can't predict the arity, unless supplying the shell command as vector which is much less elegant imho
Actually, I can put the print param first.
(defn shcomm-print [printt & comm]
(if (= :print printt) (do (println :comm comm)
(apply vector :result comm))
(do
(println :printt printt :comm comm)
(apply vector :result printt comm))))
(= (shcomm-print "a " "b " "c") (shcomm-print :print "a " "b " "c"))
But the same can be done with butlast as well.In F# there is a method for calling server functions from the client called https://github.com/Zaid-Ajaj/Fable.Remoting. Is there a similar strategy for accessing server data from the client? What's your favored strategy? (trying to stay full clj/cljs)
There are a couple RPC-style libraries floating around on GitHub, but not sure if they would be considered idiomatic. If you're looking for something bidirectional - perhaps something like https://github.com/ptaoussanis/sente is appropriate. But I find https://pathom3.wsscode.com/ to be a natural and idiomatic strategy for integrating client/server data.
Why does using a transient here doesn't make any difference in performance? It's similar to this example https://clojure.org/reference/transients#_example
(defn unrolled-2 [v2]
(loop [idx 0 agg (transient [])]
(if (< idx (- (count v2) 7))
(recur (inc idx)
(if (> 1000 (- (nth v2 (+ idx 7)) (nth v2 idx)))
(conj! agg idx)
agg))
(persistent! agg))))
I'm passing this input FWIW (def times-v (into [] (take 1e6) (iterate #(+ % (rand-int 1000)) 0)))
a) how big is v2 and how did you test? (the jvm often requires some warmup to see improvement)
b) you may be dominated by the boxed math here rather than by the collection batching. many of the math ops here will end up being boxed math, which is ~100x slower than primitive math. count and nth will return boxed numbers here. if you use long
to cast the result of count
and (set! *unchecked-math* true)
, that may help a bit
heh, jinx
agg is a coll, so the final objects are going to be boxed regardless
you could also (set! *unchecked-math* :warn-on-boxed)
to see additional warnings
the second -
is going to be boxed math as well as the nth
results will be boxed
well, you're never going to approach arrays, where the numbers can stay primitive without being boxed
you can use vector-of
to store primitives, but the generic Clojure collection interfaces to get things in and out all require boxing and that's necessarily going to be a lot of overhead. transients helps a little, but I suspect the boxing/boxed math/unboxing costs are the worst of it.
some day (maybe Java 18?) we'll get https://openjdk.java.net/jeps/401 and that will open some new options
or I guess https://openjdk.java.net/jeps/402 is the part that will likely matter to us
could potentially be a huge boost to Clojure default performance
anyway, now I'm curious to create a Java version with arraylist to see the overhead of the persistent collection
it's part of valhalla
if I understand correctly
if it is the unchecked math stuff, then you won't be measuring the "overhead" of a persistent collection, you'll be measuring the speed of math with and without having to do dispatch to determine the types of the operands
the point is, when you call a function like nth
it returns an Object so when you do math on it there is extra code to execute (type tests boxing/unboxing. etc)
Hello everyone Is there a way to get the full name of a namespace from its alias?
(ns app.foo.bar
(:require [app.x.y.z :as z]))
(? 'z)
;; => app.x.y.z
(type (? 'z))
;; => clojure.lang.Symbol