This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-04-04
Channels
- # babashka (3)
- # beginners (103)
- # calva (2)
- # cljs-dev (4)
- # clojure (23)
- # clojure-europe (16)
- # clojure-germany (1)
- # clojuredesign-podcast (2)
- # clojurescript (5)
- # cursive (4)
- # datahike (1)
- # datascript (1)
- # depstar (13)
- # fulcro (5)
- # inf-clojure (18)
- # lsp (37)
- # meander (2)
- # nrepl (2)
- # off-topic (12)
- # releases (2)
- # rewrite-clj (2)
- # shadow-cljs (9)
- # tools-deps (26)
Hi there, folks. I am wanting to do a sort-by
(or some sort of a sort) on a map with two keys in two directions. For example, I want to sort last name reverse-alphabetically, and then ties broken by first name by regular alphabetical order. So, given a list of data:
(def heroes '({:last-name "Stark", :first-name "Howard"}
{:last-name "Wilson", :first-name "Sam"}
{:last-name "Banner", :first-name "Bruce"})
{:last-name "Stark", :first-name "Tony"})
I want it to sort like this:
({:last-name "Wilson", :first-name "Sam"}
{:last-name "Stark", :first-name "Howard"}
{:last-name "Stark", :first-name "Tony"}
{:last-name "Banner", :first-name "Bruce"})
My brain is really swimming how to make this work. Can you help? 😱there's probably a more succinct version, but this seems to work:
(sort-by (juxt :last-name :first-name)
(fn [[x0 x1] [y0 y1]]
(let [c (- (compare x0 y0))]
(if-not (zero? c)
c
(compare x1 y1))))
heroes)
Ahhh, I was thinking about needing a compare
function in there, but I could not figure out how to make it work. Thanks, @smith.adriane!
you don't need that custom compare i don't think. vectors sort positionally like that by default:
(sort-by (juxt :last-name :first-name)
compare
[{:last-name "Stark", :first-name "Howard"}
{:last-name "Wilson", :first-name "Sam"}
{:last-name "Banner", :first-name "Bruce"}
{:last-name "Stark", :first-name "Tony"}])
I think the custom comparator is required to sort last name descending and first name ascending
using compare
rather than the custom comparator gives a different order than the example output
This article might be way more than you want to know, but a good understanding of its contents might be what you are looking for: https://clojure.org/guides/comparators
The only thing I could find that'd make @smith.adriane's solution more succinct is that you can reverse the order of the arguments of the first compare instead of negating the result:
(sort-by (juxt :last-name :first-name)
(fn [[x0 x1] [y0 y1]]
(let [c (compare y0 x0)]
(if-not (zero? c)
c
(compare x1 y1))))
heroes)
saves 4 whole characters! 🎉I haven't checked carefully, but there are cases where using negation can lead to very subtle and occasional bugs in comparison functions, with some examples at the article I linked. That is a much more important reason to be wary of negation there than how many characters it is.
I am trying to make a Datomic account but it asks for an Organization when I am not part of one. Can I put “None” or something?
Also: are there still free editions of Datomic available for me to test out? There were some blogposts from ~8 years ago but the only plans seem to be Solo and Production
Thank you!
Also, what would I put for my organization?
@U01ML6ZL2U8 "Free" doesn't exist any more -- that link hasn't had releases since 2019. You want the Cognitect Dev Tools to do free local dev with Datomic now. https://www.cognitect.com/dev-tools/ to download, https://docs.datomic.com/cloud/dev-local.html for more details.
Datomic is all cloud now.
Thank you for letting me know!
wait, but the release date for the most recent version says 2021-03-09 though…
The link @U0NCTKEV8 gave only has updates to 2019. The dev-local stuff has been updated recently, as you saw.
I used the Datomic Pro Free Edition thing. Is that outdated as well?
Link?
If you are just learning Datomic, use the dev-local setup. If you are planning to run Datomic in production, you need a license even for the starter edition.
You can always ask in #datomic if you're not sure how to proceed.
how can i turn a string into a map in clojurescript? i thought it was cljs.reader/read-string
but i'm not able to do normal map operations on the resultant piece even though it seems like one ought be able
What is the value of (type x)
, where x
is the return value from (cljs.reader/read-string some-string)
you're a genius! let's see...
clojurescript say function PersistentArrayMap(meta, cnt, arr, __hash)
seems correct? o.O
thanks 😃 resolved
glad you found out the issue. I was AFK for a while there.
I modified the project.clj
file with this ..
1 │ (defproject my-app "0.1.0-SNAPSHOT"
2 │ :description "testing deploy"
3 │ :url ""
4 │ :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
5 │ :url " "}
6 │ :dependencies [[org.clojure/clojure "1.10.1"]]
7 │ :main my-app.core
8 │ :target-path "target/%s"
9 │ :profiles {:uberjar {:aot :all
10 │ :jvm-opts ["-Dclojure.compiler.direct-linking=true"]}})
Here is the error message ...
No credentials found for clojars
See `lein help deploying` for how to configure credentials to avoid prompts.
Username: kyp0717
Password:
Compiling my-app.core
Created /home/phage/tmp/my-app/target/my-app-0.1.0-SNAPSHOT.jar
Wrote /home/phage/tmp/my-app/pom.xml
Could not find metadata my-app:my-app:0.1.0-SNAPSHOT/maven-metadata.xml in clojars ( )
Sending my-app/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.155005-1.jar (14k)
to
Could not transfer artifact my-app:my-app:jar:0.1.0-20210404.155005-1 from/to clojars ( ): Failed to transfer file with status code 401
Sending my-app/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.155005-1.pom (2k)
to
Could not transfer artifact my-app:my-app:pom:0.1.0-20210404.155005-1 from/to clojars ( ): Failed to transfer file with status code 401
Failed to deploy artifacts: Could not transfer artifact my-app:my-app:jar:0.1.0-20210404.155005-1 from/to clojars ( ): Failed to transfer file with status code 401
@kyp0717 what's the error you get?
xD thank you
Hmmm a 401
Unauthorized client error status
The HTTP 401 Unauthorized client error status response code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource.
@sova Do I need to set up a token? I assume NOT since it is just a simple test deployment to my group which is https://clojars.org/groups/org.clojars.kyp0717
This is a great question. I don't know anything about deploying to clojars 😄 but someone probably does.
Yes I think you need a token.
@sova I have tested my connection to clojar by successfully logging in to the group webpage. I am using the same id and password on the command line.
@kyp0717 hopefully the deploy token works.
To deploy to Clojars, you will need to authenticate yourself. Deployment authentication is done via your username and a Deploy Token.
I am trying to avoid using token as it said that token it is NOT needed for this type of deployment. Is this true?
https://github.com/clojars/clojars-web/wiki/Tutorial at the bottom note the group needs to be added to the defproject
so yours should probably be (defproject org.clojars.kyp0717/my-app "0.1.0-SNAPSHOT" ...
hi, is there a more idiomatic way to simply replace a value in map, disregarding the old val than this one:
(update map :something (fn [_ a] (function a)) 10)
you are right! I am, I didn’t realise I can use it on existing keys, I thought it was just about adding new ones
assoc, dissoc, assoc-in, reset! are all some helpful friends
@vanchuck I modifed the project.clj file to ....
(defproject org.clojars.kyp0717/my-app "0.1.0-SNAPSHOT"
:description "testsing deploy"
:url ""
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
:url " "}
:dependencies [[org.clojure/clojure "1.10.1"]]
:main my-app.core
:target-path "target/%s"
:profiles {:uberjar {:aot :all
:jvm-opts ["-Dclojure.compiler.direct-linking=true"]}})
But I got this error ...
No credentials found for clojars
See `lein help deploying` for how to configure credentials to avoid prompts.
Username: kyp0717
Password:
Compiling my-app.core
Created /home/phage/tmp/my-app/target/my-app-0.1.0-SNAPSHOT.jar
Wrote /home/phage/tmp/my-app/pom.xml
Could not find metadata org.clojars.kyp0717:my-app:0.1.0-SNAPSHOT/maven-metadata.xml in clojars ( )
Sending org/clojars/kyp0717/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.161209-1.jar (14k)
to
Could not transfer artifact org.clojars.kyp0717:my-app:jar:0.1.0-20210404.161209-1 from/to clojars ( ): Failed to transfer file with status code 401
Sending org/clojars/kyp0717/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.161209-1.pom (2k)
to
Could not transfer artifact org.clojars.kyp0717:my-app:pom:0.1.0-20210404.161209-1 from/to clojars ( ): Failed to transfer file with status code 401
Failed to deploy artifacts: Could not transfer artifact org.clojars.kyp0717:my-app:jar:0.1.0-20210404.161209-1 from/to clojars ( ): Failed to transfer file with status code 401
I have not create a github repo. Will I need to create a github repo to deploy to clojar?
Hmmm, and you made a group on clojars?
https://github.com/clojars/clojars-web/wiki/Pushing > leiningen 2.0.0 > lein deploy clojars > This will prompt you for your username and password*. For your password, you will need to create one or more https://github.com/clojars/clojars-web/wiki/Deploy-Tokens.* It is also possible to have them read from an https://github.com/technomancy/leiningen/blob/master/doc/DEPLOY.md#authentication.
@sova Yes. I believe this is my group on clojars ...https://clojars.org/groups/org.clojars.kyp0717
Hiya, is there a way of simplifying these nested if statements (my code):
(defn main [severity]
(println (str "We're")
(if (= severity :mild)
"mildly inconvenienced."
(if (= severity :severe)
"doomed."))))
into something more concise like this?:
(defn math [opr x y]
(({"add" +, "times" *} opr) x y))
Here's where i found the more concise function https://stackoverflow.com/questions/21681374/clojure-with-multiple-if-statements/21684980#21684980cond
or case
will both let you remove that nesting.
Or you can just use a hash map, keyed by :mild
and :severe
with strings as the values.
(defn main [severity]
(println "We're" (severity {:mild "mildly inconvenienced." :severe "doomed."})))
user=> (defn main [severity]
(println "We're" (severity {:mild "mildly inconvenienced." :severe "doomed."})))
#'user/main
user=> (main :severe)
We're doomed.
nil
user=> (main :mild)
We're mildly inconvenienced.
nil
user=> (main :what)
We're nil
nil
user=>
Note the last case.Here's a variant that provides a "not found" value:
user=> (defn main [severity]
(println "We're" (severity {:mild "mildly inconvenienced." :severe "doomed."} "OK.")))
#'user/main
user=> (main :what)
We're OK.
nil
user=>
Also (hash-map kw not-found)
also means (get hash-map kw not-found)
Hi everyone, I have 3 lists of numbers with values 0
or 30/40/50
I want to create a new list where it gives me true (or 1) when the 3 lists are all not= 0
What might be the best way to do this?
Wanted to do map over and
but could only do
(and
(map #(not= 0 %) [0 0 0 0 40 0])
(map #(not= 0 %) [0 0 0 0 0 30])
(map #(not= 0 %) [0 0 0 50 0 0]))
Per the docstring
Evaluates exprs one at a time, from left to right. If a form
returns logical false (nil or false), and returns that value and
doesn't evaluate any of the other expressions, otherwise it returns
the value of the last expr. (and) returns true.
@zackteo It’s not a strictly Boolean operation — because false
/`nil` are “falsey” and everything else is “truthy” in Clojure.
Right right :thinking_face: how do I map over and
then? Is that possible? I realise there's another way to solve my problem already but don't quite understand why (map and ...)
does not work
A hacky way to make it work is:
(let [v1 [true false]
v2 [true true]
v3 [false false]]
(mapv #(eval `(and ~@%)) [v1 v2 v3]))
But (eval …) is generally not recommended if another solution is possible (almost always is)
not sure what you mean by map
over and
. Can you provide an example output? My guess is that you want some
somewhere
@smith.adriane I would like to be able to do this I believe
(map and
(map #(not= 0 %) [0 0 0 0 40 0])
(map #(not= 0 %) [0 0 0 0 0 30])
(map #(not= 0 %) [0 0 0 50 0 0]))
I think you're looking for every?
, @zackteo
like this?
(map (fn [& xs]
(every? identity xs))
(map #(not= 0 %) [1 0 0 0 40 0])
(map #(not= 0 %) [1 0 0 0 0 30])
(map #(not= 0 %) [1 0 0 50 0 0]))
;; (true false false false false false)
I changed the example slightly so that there would be at least one true result
I think this gives the same result but I'm not 100% sure
(map (fn [& xs]
(not-any? #(= 0 %) xs))
[1 0 0 0 40 0]
[1 0 0 0 0 30]
[1 0 0 50 0 0])
user=> (map #(not-any? zero? %&)
[1 0 0 0 40 0]
[1 0 0 0 0 30]
[1 0 0 50 0 0])
(true false false false false false)
Using zero?
is more idiomatic than #(= 0 %)
and then you can use #
for the anonymous mapped function (`%&` is not used very often but it’s a good fit here)Also, could I ask with two lists [43 51 37 41]
and [true false true false]
How do I get something like [43 0 37 0]
where it returns me the value if it is true and 0 if false?
You can map over both colls simultaneously and have a condition to either return the num or 0 if false
(mapv
(fn [x1 x2]
(if (true? x2) x1 0))
[43 51 37 41]
[true false true false])
=> [43 0 37 0](fn […]) should take a number of arguments equal to the number of collections you’re going over at the same time