beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
Scott Starkey 2021-04-04T00:02:24.012600Z

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? ๐Ÿ˜ฑ

phronmophobic 2021-04-04T00:13:29.012700Z

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)

Scott Starkey 2021-04-04T00:20:38.012900Z

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!

๐Ÿ‘ 1
dpsutton 2021-04-04T00:45:40.013400Z

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"}])

phronmophobic 2021-04-04T00:47:45.013600Z

I think the custom comparator is required to sort last name descending and first name ascending

phronmophobic 2021-04-04T00:48:33.013800Z

using compare rather than the custom comparator gives a different order than the example output

dpsutton 2021-04-04T00:49:37.014300Z

Oh sorry I missed descending. Youโ€™re totally right

2021-04-04T01:07:32.014500Z

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

๐Ÿ‘ 3
๐Ÿ’ฏ 1
๐Ÿ‘† 1
Dave A 2021-04-04T03:44:01.014800Z

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! ๐ŸŽ‰

Michael Lan 2021-04-04T04:31:20.015600Z

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?

Michael Lan 2021-04-04T04:33:29.015800Z

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

2021-04-04T04:33:55.016Z

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.

2021-04-04T04:35:54.016200Z

https://my.datomic.com/downloads/free

Michael Lan 2021-04-04T04:37:04.016500Z

Thank you!

Michael Lan 2021-04-04T04:38:16.016700Z

Also, what would I put for my organization?

seancorfield 2021-04-04T05:00:53.016900Z

@michaellan202 "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.

seancorfield 2021-04-04T05:01:08.017100Z

Datomic is all cloud now.

Michael Lan 2021-04-04T05:35:03.017300Z

Thank you for letting me know!

Michael Lan 2021-04-04T05:37:12.017500Z

wait, but the release date for the most recent version says 2021-03-09 thoughโ€ฆ

seancorfield 2021-04-04T05:48:19.017900Z

The link @hiredman gave only has updates to 2019. The dev-local stuff has been updated recently, as you saw.

Michael Lan 2021-04-04T06:01:19.018100Z

I used the Datomic Pro Free Edition thing. Is that outdated as well?

seancorfield 2021-04-04T06:05:33.018300Z

Link?

seancorfield 2021-04-04T06:07:43.018500Z

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.

๐Ÿ‘ 1
seancorfield 2021-04-04T06:08:42.018700Z

You can always ask in #datomic if you're not sure how to proceed.

sova-soars-the-sora 2021-04-04T14:54:29.021800Z

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

2021-04-04T14:55:19.021900Z

What is the value of (type x), where x is the return value from (cljs.reader/read-string some-string)

sova-soars-the-sora 2021-04-04T15:00:37.022200Z

you're a genius! let's see...

sova-soars-the-sora 2021-04-04T15:01:11.022400Z

clojurescript say function PersistentArrayMap(meta, cnt, arr, __hash)

sova-soars-the-sora 2021-04-04T15:01:37.022600Z

seems correct? o.O

sova-soars-the-sora 2021-04-04T15:05:43.022800Z

thanks ๐Ÿ˜ƒ resolved

Phat Ky 2021-04-04T15:16:37.023500Z

Hi. Please help me publish my test app on clojar.

Phat Ky 2021-04-04T15:17:07.024100Z

I created a test app with this cmd lein new app my-app

Phat Ky 2021-04-04T15:18:04.024800Z

I modified the project.clj file with this ..

1   โ”‚ (defproject my-app "0.1.0-SNAPSHOT"
   2   โ”‚   :description "testing deploy"
   3   โ”‚   :url "<https://clojars.org/groups/org.clojars.kyp0717>"
   4   โ”‚   :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
   5   โ”‚             :url "<https://www.eclipse.org/legal/epl-2.0/>"}
   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"]}})

Phat Ky 2021-04-04T15:18:37.025600Z

Finally, I published with this cmd lein deploy clojars

Phat Ky 2021-04-04T15:19:02.026Z

My version of lein is Leiningen 2.9.5 on Java 11.0.10 OpenJDK 64-Bit Server VM

Phat Ky 2021-04-04T15:19:12.026300Z

What am I doing wrong?

Phat Ky 2021-04-04T15:50:28.026800Z

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 (<https://repo.clojars.org/>)
Sending my-app/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.155005-1.jar (14k)
    to <https://repo.clojars.org/>
Could not transfer artifact my-app:my-app:jar:0.1.0-20210404.155005-1 from/to clojars (<https://repo.clojars.org/>): Failed to transfer file <https://repo.clojars.org/my-app/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.155005-1.jar> with status code 401
Sending my-app/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.155005-1.pom (2k)
    to <https://repo.clojars.org/>
Could not transfer artifact my-app:my-app:pom:0.1.0-20210404.155005-1 from/to clojars (<https://repo.clojars.org/>): Failed to transfer file <https://repo.clojars.org/my-app/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.155005-1.pom> 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 (<https://repo.clojars.org/>): Failed to transfer file <https://repo.clojars.org/my-app/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.155005-1.jar> with status code 401

sova-soars-the-sora 2021-04-04T15:50:28.026900Z

@kyp0717 what's the error you get?

sova-soars-the-sora 2021-04-04T15:50:33.027100Z

xD thank you

sova-soars-the-sora 2021-04-04T15:50:55.027500Z

Hmmm a 401

sova-soars-the-sora 2021-04-04T15:51:20.027800Z

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.

Phat Ky 2021-04-04T15:52:38.029Z

@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

sova-soars-the-sora 2021-04-04T15:53:07.029700Z

This is a great question. I don't know anything about deploying to clojars ๐Ÿ˜„ but someone probably does.

sova-soars-the-sora 2021-04-04T15:54:06.030700Z

https://github.com/clojars/clojars-web/wiki/Deploy-Tokens

sova-soars-the-sora 2021-04-04T15:54:14.031100Z

Yes I think you need a token.

Phat Ky 2021-04-04T15:54:14.031200Z

@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.

sova-soars-the-sora 2021-04-04T15:55:19.031600Z

@kyp0717 hopefully the deploy token works.

sova-soars-the-sora 2021-04-04T15:55:53.032500Z

To deploy to Clojars, you will need to authenticate yourself. Deployment authentication is done via your username and a Deploy Token.

Phat Ky 2021-04-04T15:56:01.032700Z

I am trying to avoid using token as it said that token it is NOT needed for this type of deployment. Is this true?

Dave A 2021-04-04T15:57:28.033200Z

https://github.com/clojars/clojars-web/wiki/Tutorial at the bottom note the group needs to be added to the defproject

Dave A 2021-04-04T15:59:19.034300Z

so yours should probably be (defproject org.clojars.kyp0717/my-app "0.1.0-SNAPSHOT" ...

Dimitar Uzunov 2021-04-04T16:05:50.036Z

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)

Phat Ky 2021-04-04T16:06:09.036300Z

@vanchuck I modifed the project.clj file to ....

(defproject org.clojars.kyp0717/my-app "0.1.0-SNAPSHOT" 
  :description "testsing deploy"
  :url "<https://clojars.org/groups/org.clojars.kyp0717>"
  :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
            :url "<https://www.eclipse.org/legal/epl-2.0/>"}
  :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"]}})

Phat Ky 2021-04-04T16:06:25.036600Z

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 (<https://repo.clojars.org/>)
Sending org/clojars/kyp0717/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.161209-1.jar (14k)
    to <https://repo.clojars.org/>
Could not transfer artifact org.clojars.kyp0717:my-app:jar:0.1.0-20210404.161209-1 from/to clojars (<https://repo.clojars.org/>): Failed to transfer file <https://repo.clojars.org/org/clojars/kyp0717/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.161209-1.jar> 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 <https://repo.clojars.org/>
Could not transfer artifact org.clojars.kyp0717:my-app:pom:0.1.0-20210404.161209-1 from/to clojars (<https://repo.clojars.org/>): Failed to transfer file <https://repo.clojars.org/org/clojars/kyp0717/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.161209-1.pom> 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 (<https://repo.clojars.org/>): Failed to transfer file <https://repo.clojars.org/org/clojars/kyp0717/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.161209-1.jar> with status code 401

Phat Ky 2021-04-04T16:07:58.037700Z

I have not create a github repo. Will I need to create a github repo to deploy to clojar?

schmee 2021-04-04T16:09:44.037900Z

are you looking for assoc?

๐Ÿ™ 1
Dimitar Uzunov 2021-04-04T16:12:11.038100Z

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

sova-soars-the-sora 2021-04-04T16:13:19.038400Z

assoc, dissoc, assoc-in, reset! are all some helpful friends

sova-soars-the-sora 2021-04-04T16:14:11.039Z

Hmmm, and you made a group on clojars?

Dave A 2021-04-04T16:14:24.039400Z

I think @sova is right, you need to use deploy tokens:

Dave A 2021-04-04T16:14:50.039900Z

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.

Phat Ky 2021-04-04T16:15:51.040500Z

I will create a token. Will I need to create a github repo too?

Dave A 2021-04-04T16:16:13.040700Z

don't think so, docs don't mention github

Phat Ky 2021-04-04T16:17:30.041400Z

@sova Yes. I believe this is my group on clojars ...https://clojars.org/groups/org.clojars.kyp0717

Phat Ky 2021-04-04T16:18:00.041500Z

Ok thanks

2021-04-04T18:34:53.043500Z

glad you found out the issue. I was AFK for a while there.

Billy Gigurtsis 2021-04-04T18:56:59.045600Z

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#21684980

seancorfield 2021-04-04T19:08:00.046700Z

cond or case will both let you remove that nesting.

seancorfield 2021-04-04T19:08:52.047800Z

Or you can just use a hash map, keyed by :mild and :severe with strings as the values.

seancorfield 2021-04-04T19:10:31.049100Z

(defn main [severity]
  (println "We're" (severity {:mild "mildly inconvenienced." :severe "doomed."})))

seancorfield 2021-04-04T19:11:34.049600Z

@bgigurtsis

user=&gt; (defn main [severity]
  (println "We're" (severity {:mild "mildly inconvenienced." :severe "doomed."})))
#'user/main
user=&gt; (main :severe)
We're doomed.
nil
user=&gt; (main :mild)
We're mildly inconvenienced.
nil
user=&gt; (main :what)
We're nil
nil
user=&gt;
Note the last case.

seancorfield 2021-04-04T19:12:44.050Z

Here's a variant that provides a "not found" value:

user=&gt; (defn main [severity]
  (println "We're" (severity {:mild "mildly inconvenienced." :severe "doomed."} "OK.")))
#'user/main
user=&gt; (main :what)
We're OK.
nil
user=&gt;

Billy Gigurtsis 2021-04-04T19:13:27.050900Z

That is exactly what I was looking for, thank you.

seancorfield 2021-04-04T19:13:35.051100Z

(kw hash-map not-found) is like (get hash-map kw not-found)

๐Ÿ‘ 1
seancorfield 2021-04-04T19:13:56.051600Z

Also (hash-map kw not-found) also means (get hash-map kw not-found)

zackteo 2021-04-04T21:08:17.055400Z

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?

zackteo 2021-04-04T21:08:40.055900Z

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]))

zackteo 2021-04-04T21:09:08.056600Z

Where I don't quite understand why and here just gives me the value of the last list

seancorfield 2021-04-04T21:12:25.057100Z

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.

seancorfield 2021-04-04T21:13:13.057900Z

@zackteo Itโ€™s not a strictly Boolean operation โ€” because false/`nil` are โ€œfalseyโ€ and everything else is โ€œtruthyโ€ in Clojure.

zackteo 2021-04-04T21:28:39.058Z

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

phronmophobic 2021-04-04T21:35:32.059Z

not sure what you mean by map over and. Can you provide an example output? My guess is that you want some somewhere

zackteo 2021-04-04T21:36:20.059400Z

@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]))

pavlosmelissinos 2021-04-04T21:40:44.060100Z

I think you're looking for every? , @zackteo

phronmophobic 2021-04-04T21:40:45.060200Z

like this?

(map (fn [&amp; 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)

โ˜๏ธ 1
phronmophobic 2021-04-04T21:41:04.060700Z

I changed the example slightly so that there would be at least one true result

zackteo 2021-04-04T21:43:28.061100Z

Wow okay okay. Never saw the need to use every? until now ๐Ÿ˜ฎ

zackteo 2021-04-04T21:43:56.061500Z

Thanks!

pavlosmelissinos 2021-04-04T21:52:19.063Z

I think this gives the same result but I'm not 100% sure

(map (fn [&amp; xs]
       (not-any? #(= 0 %) xs))
     [1 0 0 0 40 0]
     [1 0 0 0 0 30]
     [1 0 0 50 0 0])

seancorfield 2021-04-04T22:04:50.064200Z

user=&gt; (map #(not-any? zero? %&amp;)
     [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)

๐Ÿ’ฏ 3
raspasov 2021-04-04T22:18:04.064500Z

(map and ...) does not work because and is a macro

zackteo 2021-04-04T22:26:13.066Z

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?

zackteo 2021-04-04T22:26:30.066500Z

My first instinct if any is using for but not too sure actually

Lu 2021-04-04T22:28:11.067700Z

You can map over both colls simultaneously and have a condition to either return the num or 0 if false

zackteo 2021-04-04T22:29:36.068400Z

How do I choose which coll to access in a map ? ๐Ÿ˜ฎ

raspasov 2021-04-04T22:30:07.068700Z

(mapv
 (fn [x1 x2]
  (if (true? x2) x1 0))
 [43 51 37 41]
 [true false true false])
=> [43 0 37 0]

raspasov 2021-04-04T22:30:22.069100Z

x1 is each item in the first coll, x2 is each item in the second coll

raspasov 2021-04-04T22:31:35.070900Z

(fn [โ€ฆ]) should take a number of arguments equal to the number of collections youโ€™re going over at the same time

raspasov 2021-04-04T22:32:06.071500Z

A hacky way to make it work is:

(let [v1 [true false]
      v2 [true true]
      v3 [false false]]
 (mapv #(eval `(and ~@%)) [v1 v2 v3]))

zackteo 2021-04-04T22:32:10.071800Z

Ohhh okay okay! I was thinking about that. Cause the functions I have been using in map seems to like work uniformly across the colls like +

raspasov 2021-04-04T22:32:29.071900Z

But (eval โ€ฆ) is generally not recommended if another solution is possible (almost always is)

zackteo 2021-04-04T22:33:21.072300Z

Thanks everyone for your help!! ๐Ÿ˜„

๐Ÿ‘ 2
zackteo 2021-04-04T22:34:01.073100Z

Learnt quite a fair bit from all the responses!

1
๐Ÿ‘Œ 1