This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-07-04
Channels
- # announcements (6)
- # babashka (5)
- # beginners (57)
- # biff (6)
- # business (32)
- # clj-together (1)
- # clojars (10)
- # clojure (56)
- # clojure-europe (76)
- # clojure-nl (4)
- # clojure-norway (40)
- # clojure-serbia (1)
- # clojure-spec (5)
- # clojure-uk (10)
- # clojurescript (3)
- # cursive (12)
- # data-science (1)
- # datascript (4)
- # datomic (35)
- # docs (4)
- # emacs (28)
- # events (5)
- # hyperfiddle (9)
- # matrix (1)
- # off-topic (28)
- # practicalli (4)
- # re-frame (14)
- # shadow-cljs (2)
- # testing (5)
I'm missing something, is there a "rest" concept when destructuring keys in a function argument?
I'm trying to cascade props down into a react component.
(defn button [{:keys [isLoading variant size class-name ref] :as props} children]...)
But using the :as keyword gets me all the values, including the ones I've named, I'd like a :rest option to grab everything else?
Any ideas or direction would be greatly appreciated.
no, there is nothing like that in destructure syntax yet
there is a request to add :rest directive - https://ask.clojure.org/index.php/11184/rest-for-map-destructuring?show=11184#q11184
A second binding using dissoc
on the right hand side seems like it would do the trick, if I follow you correctly. It might help to describe your motivation some more.
Persistent data structures, higher-order functions, namespaced keywords, an interest in host-level performance, and clojure.spec suggest a philosophy of tolerating unexpected map keys. In other words, use what you need and ignore the rest. After all, the map with the excess is ready free-of-charge, while on the other hand making a new map takes time and, because of persistent structures, is usually pointless. Given that it's pretty easy to remove keys, when absolutely necessary, e.g., (reduce dissoc props [:boats :planes])
, it's not a surprise that destructuring does not have a feature for the antipattern. @U04V4KLKCβs link had an interesting comment, which was that if this comes up often in your program and you don't like repeating the list of keys, you can make a macro.
I did end up using dissoc, I normally would just leave the keys alone. As Phill says tolerating the unexpected keys. Unfortunately its interop with Javascript which isn't as sensible. I can definitely see why the core of clojure would not use this feature, I think it would be mostly helpful when using interop.
I have these lines of code in a .clj file. When I try to run the file in a command-line, I am getting the error below: Execution error (ClassCastException) at user/eval1 (stat.clj:1). class java.lang.Character cannot be cast to class clojure.lang.Named (java.lang.Character is in module java.base of loader 'bootstrap'; clojure.lang.Named is in unnamed module of loader 'app') (require '[clojure.string :as str] '[org.clojure/math.numeric-tower "0.0.5" :as math]) ;;(def my_dataset (list 10 7 14 23 15 7 32 23)) ;;(def my_dataset (list 3 5 9 5 7 2)) (def my_dataset (list 67 66 71 33 63 72 74 58 78 75 67)) (defn comma-separated [coll] (str/join ", " coll)) (defn dataset-sum [coll] (reduce + coll)) (println (str "The elements in the dataset are the ff: " (comma-separated my_dataset) ".")) (println (str "The elements in the dataset are the ff: " (sort my_dataset) ".")) (println (str "The elements in the dataset in sorted order: " (comma-separated (sort my_dataset)) ".")) (println (str "The number of elements in the data set is " (count my_dataset) ".")) (println (str "The sum of all numbers in the dataset is " (dataset-sum my_dataset) ".")) (defn mode [coll] (let [counts (frequencies coll) ;; {7 2, 10 1, 14 1, 15 1, 23 1, 32 1} max-count (apply max (vals counts)) ;; 2 mode-entries (filter #(= max-count (val %)) counts)] ;; (2) (keys mode-entries))) ;; 7 (println (str "The mode of the dataset is " (mode my_dataset) ".")) (defn mean [coll] (if (empty? coll) nil (format "%.2f" (/ (float (reduce + coll)) (count coll))))) (println (str "The mean of the dataset is " (mean my_dataset) ".")) (defn median [coll] (let [sorted (sort coll) len (count sorted) mid (quot len 2)] (if (even? len) (/ (+ (nth sorted (dec mid)) (nth sorted mid)) 2) (nth sorted mid)))) (println (str "The median of the dataset is " (median my_dataset)".")) (defn collection-range [coll] (-(apply max coll) (apply min coll))) (println (str "The range of the dataset is " (collection-range my_dataset)".")) ;; define a function that calculates the standard deviation ;(defn standard-deviation [coll] ; (let [n (count coll) ; mean (mean coll) ; squared-deviations (map #(Math/pow (- % mean) 2) coll) ; variance (/ (reduce + squared-deviations) n)] ; (Math/sqrt variance))) (defn standard-deviation [coll] (let [numeric-coll (filter number? coll) ; Filter out non-numeric values n (count numeric-coll) mean (mean numeric-coll) squared-deviations (map #(math/expt (- % mean) 2) numeric-coll) variance (/ (reduce + squared-deviations) n)] (Math/sqrt variance))) (println (str "The standard deviation of the dataset is " (standard-deviation my_dataset) "."))
The require syntax is not right, looks like you are confusing dependencies with namespaces, you have :
(require '[org.clojure/math.numeric-tower "0.0.5" :as math])
with a artifact description and a version number there. Namespaces don't have versions, you should write the require like this :
(require '[clojure.math.numeric-tower :as math])
but after you are in a system that has org.clojure/math.numeric-tower {:mvn/version "0.0.5"}
also how are you trying to run this file?
You also have another typing issue, which is your mean
fn is returning the mean as a string, so when you then try to do math with it you will get a class cast exception
so if you fix your require and also remove the format
from your mean
function you can run the entire script like this :
clj -Sdeps '{:deps {org.clojure/math.numeric-tower {:mvn/version "0.0.5"}}}' script.clj
also if you are starting with Clojure developing your programs by running scripts like this is very time consuming. It is better to setup your editor to start a repl so you can evaluate and try each expression from it, and maybe just run it as a script when you know everything works. It takes some time to get used to it but really worth it
I run the file in power shell of windows using wsl. In the command-line, I execute this command: clojure -M stat.clj
After removing the version number, I still get this error: Execution error (FileNotFoundException) at user/eval1 (stat.clj:1). Could not locate math/numeric_tower__init.class, math/numeric_tower.clj or math/numeric_tower.cljc on classpath. Please check that namespaces with dashes use underscores in the Clojure file name.
it is not only about removing the version number, you also need to write it without the slash and with the correct namespace like I wrote before, copy this :
(require '[clojure.math.numeric-tower :as math])
also looking at your code you don't need that numeric-tower dependency at all, you can just (require '[clojure.math :as math])
and then just use math/sqrt
and math/pow
, then you can run your script much simpler like:
clj script.clj
I did the following: 1. (require '[clojure.string :as str] '[clojure/math :as math]) I edit the code from this: '[clojure/math.numeric-tower :as math] To this: '[clojure/math :as math] 2. clj -Mdeps '{:deps {org.clojure/math.numeric-tower {:mvn/version "0.0.5"}}}' stat.clj This command downloaded the dependencies however, at the bottom, it threw an error like shown below: Execution error (FileNotFoundException) at http://java.io.FileInputStream/open0 (FileInputStream.java:-2). {:deps {org.clojure/math.numeric-tower {:mvn/version "0.0.5"}}} (No such file or directory) 3. clj -M stat.clj Execution error (FileNotFoundException) at user/eval1 (stat.clj:9). Could not locate math__init.class, math.clj or math.cljc on classpath. This threw an error as as it cannot find the '[clojure/math :as math].
the require is wrong, copy what I wrote, you are using slashes instead of dots, it should be (require '[clojure.math :as math])
Also you don't need the -M for executing the script, just do clj stat.clj
That was an oversight on my part. But even after fixing it, I still get this error: Execution error (ClassCastException) at user/standard-deviation$fn (stat.clj:127). class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')
yes, that is what I comment before
> You also have another typing issue, which is your mean
fn is returning the mean as a string, so when you then try to do math with it you will get a class cast exception
it will work if you remove the (format ...) you have in your mean fn
Yes, it did. If I do not use the format function, how will I format the results into two decimal places?
you should format them just for printing, so you can do it on your printlns
ah ok
like :
(println (format "The mean of the dataset is %0.2f " (mean my_dataset)))
Ok. Thanks a lot
I only encounter this error after I added these lines below:
(defn standard-deviation [coll] (let [numeric-coll (filter number? coll) ; Filter out non-numeric values n (count numeric-coll) mean (mean numeric-coll) squared-deviations (map #(math/expt (- % mean) 2) numeric-coll) variance (/ (reduce + squared-deviations) n)] (Math/sqrt variance))) (println (str "The standard deviation of the dataset is " (standard-deviation my_dataset) "."))
Is there a way to persist REPL state automatically, such that one could recover from, e.g., a power failure or an accidental termination (of the repl or the parent process or whatever)?
imho, the best way to persist REPL state is to write AND execute code directly from the editor. There are clojure plugins that allow that for almost every popular editors and IDEs
for example you can create a comment block right in your project's files:
(comment
(def tmp-value 42)
(run-experiment tmp-value)
)
(I was thinking the question was about fully saving a JVM state, like jvm snapshot), but @U04V4KLKC interpretation makes more sense :))
you can also implement your own eval
which persists vars to a kv database and load it when you start π
slightly more complicated with defn
s because you'll have to either find a way to persist closures or do something else
@UK0810AQ2 (def fuuuuu (range))
π
even vars can give you a headache π
@U04V4KLKC nippy can handle ranges, no?
I don't think so
but I rarely use it so maybe I'm missing something like custom serde
Can you expand on that @UK0810AQ2?
The dumbest way to do it is just append to a file every form you eval, then loading that file should recreate your REPL state exactly. Everything afterwards is optimization
hm true
Hell, if you can serialize everything (you can't but we're theorizing), replace the implementation of namespaces to use a database and save all values there
yes, yes, I am looking at my question differently now. If I have data to persist there are plenty of options and if I have code to persist I have an editor.
But if you have entire REPL state to persist, there's still no optimal solution for your problem, although #C035GRLJEP8 does interesting things in that direction
#C035GRLJEP8 is notebooking iirc
from the guy who doesnβt like notebooks. very cool.
I guess the complicated part around the event sourcing repl or even just having a big comment with a lot of forms are side effects, since you are re running them for the side effects to recover you repl state, but also mixed will be side effects that aren't related to the JVM process state but with something like your DB state, that you don't need to rebuild because it never got destroyed
That's where you start optimizing and replace the results of side effects with values
you can do that pretty much indefinitely as long as you aren't dealing with infinite stuff or things which aren't values
I don't think that is possible to automate, you may had executed a fn-call that incremented an atom and created a file on the disk, so for recovering your repl state you are interested in the first side effect but no the second one