beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
Aron 2021-04-21T10:50:36.282400Z

Is #(nth % 1) exactly the same as first?

2021-04-21T11:04:20.282500Z

this will be equivalent of second and unlike second it will fail if collection is empty consider this #(nth % 0 nil)

Aron 2021-04-21T12:38:28.282700Z

I see, thanks for the correction!

Aron 2021-04-21T12:41:32.282900Z

"will fail" means something like an out of bound exception?

2021-04-21T12:47:54.283100Z

yes, IndexOutOfBoundsException should be thrown

1
Edward Ciafardini 2021-04-21T13:07:13.285700Z

Hello. I'm having an issue using slurp. I was following this article to get some experience using it: https://practicalli.github.io/blog/posts/consuming-apis-with-clojure/ When I run the command:

(slurp "<http://www.gutenberg.org/cache/epub/844/pg844.txt>")
The result looks like this: 9vTƌE,QZ5,V.&?7WIrrP36틈]H<,ASulbdx[L!ż\tzI:$\r<?:r#F@kk-ד=\tfcZw.f\nNn3{O{\b2R|%{\r)Z4C!tH\\ά5!m£\n%wMN%{ĆX^kCNqd_.J#87S<[tSϦof#:}3a#B\rTci\r%oޅL!=k<_%?\f*'aƊm#wn2zEEzg]$բ|dCUWqٙܟ4D5߱'http://fI.GY \nV;r@&ȱ}Im2Y'8r\fjt7#=@Lp^ (this is only a portion of the output) I tried adding a param for encoding: (slurp "http://www.gutenberg.org/cache/epub/844/pg844.txt" :encoding "UTF-8") It's still giving me the cryptic response.

alexmiller 2021-04-21T13:10:38.286100Z

I think you're getting a gzipped response

alexmiller 2021-04-21T13:11:04.286400Z

you may not be able to fix that with slurp

alexmiller 2021-04-21T13:14:08.287600Z

slurp is a quick and dirty tool, maybe too quick and dirty for this task - you can either use your browser to save that page to disk, then open it from disk with slurp, or use something like https://github.com/dakrone/clj-http as a real http client

alexmiller 2021-04-21T13:14:39.288300Z

or I guess you could theoretically use the gzip stream stuff built into Java to decode the slurp output probably

Edward Ciafardini 2021-04-21T13:34:03.288700Z

Thanks!

Johan Basson 2021-04-21T14:06:59.288900Z

Good day. Where can I get a tutorial or guide on how to use the repl?

Dimitar Uzunov 2021-04-21T14:14:52.289200Z

I think youtube might be the best place: https://www.youtube.com/watch?v=gIoadGfm5T8

Dimitar Uzunov 2021-04-21T14:15:13.289700Z

its interactive so it is easier to demonstrate with a video than a guide

Dimitar Uzunov 2021-04-21T14:16:28.290100Z

and there is the official clojure guide: https://clojure.org/guides/repl/introduction

Johan Basson 2021-04-21T14:30:05.290300Z

Thank you

Karo 2021-04-21T17:11:26.294100Z

Hi team, how can I idiomatically replace two maps in this data with other maps that has same keys but different values

[{"key1" "value1"} {"key2" "value2"} {"key3" "value3"} {"key4" "value4"}]
want to update first with {"key1" "value100"} and second {"key1" "value200"} order of maps can be changed so update based on index is not best choice.

2021-04-21T17:21:20.294200Z

(into [] (map #(replace-map %))
      [{"key1" "value1"} {"key2" "value2"} {"key3" "value3"} {"key4" "value4"}])
good case for using transducer you need to implement replace-map function which should take a single map from collection and based on condition either leave it intact or change based on your logic

👍 1
1
roelof 2021-04-21T19:33:25.295200Z

just curious

1
roelof 2021-04-21T19:35:20.297400Z

On other languages I had to do a challenge where I had to calculate bowling scores and keep track on spare and strikes . If I have a collection like this : ( 6 4 0 0 10 4 3 0 0 0 0 0 ) How in clojure do I calculate the total score

alexmiller 2021-04-21T19:36:07.297700Z

(reduce + scores)

roelof 2021-04-21T19:37:00.299200Z

hmm, that simple. but on a strike the next two scores need to be doubled

alexmiller 2021-04-21T19:37:05.299400Z

or maybe you need to calculate the bonuses over the top of that - still doable with reduce

roelof 2021-04-21T19:37:15.299600Z

yes, I have

alexmiller 2021-04-21T19:38:45.300600Z

I think you need to track rolls per frame to distinguish strikes and spares though

dpsutton 2021-04-21T19:40:14.301700Z

(take 10 (map vector (range) (partition-all 3 1 '( 6 4 0 0 10 4 3 0 0 0 0 0 )))) gets you the 10 frames with frame number and later scores that can affect the score. But impossible to calculate without knowing which 10's are strikes and which are spares

roelof 2021-04-21T19:40:48.302200Z

easy a 10 is a strike

roelof 2021-04-21T19:41:33.303200Z

and when two seperate numbers are together 10 it is a strike so in my made up it the 6 and 4

roelof 2021-04-21T19:42:47.304200Z

so the frames are frame 1 : 6 4 frame 2 : 0 0 frame 3: 10 frame 4: 4 5 frame 5 till 10 : 0 0

dpsutton 2021-04-21T19:43:26.304600Z

oh. making this a variable length encoding adds lots of complexity and quite possibly an impossible ambiguity

roelof 2021-04-21T19:44:03.305200Z

I know. it was a exercism challenge I tried to do in ruby and haskell

sova-soars-the-sora 2021-04-22T22:05:12.401100Z

maybe pre-process the list to create a list of numbers you can simply add. like a raw-score that you derive from the input score sheet.

sova-soars-the-sora 2021-04-22T22:07:15.401300Z

you can split the input vector on tens, for example

roelof 2021-04-24T17:50:48.043100Z

Maybe, I do not see totally where you are heading to @sova

dpsutton 2021-04-21T19:44:57.305500Z

whatever you did in haskell will most likely work almost identically here

roelof 2021-04-21T19:45:30.305900Z

I could not solve this one in both 😞

Eric Ihli 2021-04-21T19:49:02.308400Z

Is there something like take-through (like take-while but including the next after the predicate return value changes) in Clojure? I see it was https://groups.google.com/g/clojure-dev/c/NaAuBz6SpkY but I can't find it in the docs now. If there's not, then is there a commonly accepted library of "extended utilities" that has it?

Alexander Kaiser 2021-04-21T20:06:07.309900Z

Recommended way for id-based lookups? I want to express the following:

(def input
  {:artists [#:artist{:id 0,
                      :founding-date 2000}],
   :albums [#:album{:id 0,
                    :artist 0,
                    :release-date 2002}]})

(def output
  [#:album{:id 0,
           :artist 0,
           :release-date 2002,
           :artist-years-active-at-release 2}]
  )
One possible solution:
(defn group-by-version [{:keys [artists albums]}]
  (let [artists-by-id (group-by :artist/id artists)]
    (mapv
     (fn[album]
       (-&gt;&gt;
        ;; before using first like this i should (spec) check that :artist/id is distinct in artist or use something like only from the tupelo library. Omitted for readability.
        (first (get artists-by-id (album :album/artist)))
        ((fn[artist] (- (:album/release-date album)
                        (:artist/founding-date artist))))
        (assoc album :album/artist-years-active-at-release)
        )
       )
     albums
     ))
  )
(group-by-version input)
However this feels unnecessary verbose and I especially would like to replace the group-by part. Is it better to use spectre or meander for these kinds of operations? Should I structure the data in a different way? Should I transform the data before I do those operations? E.g. with lilactown's new autonormal? I am missing something very obvious here?

2021-04-21T20:10:32.310Z

Maybe take-upto from https://github.com/weavejester/medley fits the bill

🙏 1
Aron 2021-04-21T20:20:46.312400Z

If I pass a map with a single key-value pair to a function, how can I destructure the name of the key as a string into a symbol?

seancorfield 2021-04-21T20:26:51.312500Z

dev=&gt; (take-while even? [2 4 6 8 10 11 12 13])
(2 4 6 8 10)
dev=&gt; (into [] (halt-when (complement even?) conj!) [2 4 6 8 10 11 12 13])
[2 4 6 8 10 11]

🤙 1
seancorfield 2021-04-21T20:27:55.312700Z

halt-when is a bit strange to use because in the 2-arity version it needs to know about the internals of the transduction, since the accumulator here is a transient.

seancorfield 2021-04-21T20:28:45.313Z

@ghadi ^ this seems odd to me — am I using this correctly?

ghadi 2021-04-21T20:29:37.313700Z

Debatable whether this is a bug

ghadi 2021-04-21T20:29:59.314400Z

There is a jira for it with more details

seancorfield 2021-04-21T20:30:10.314600Z

Ah, OK. Will look it up. Thanks!

seancorfield 2021-04-21T20:31:32.315Z

For reference https://clojure.atlassian.net/browse/CLJ-2556

ghadi 2021-04-21T20:33:41.315200Z

there is a bug IMHO, but it's in into not halt-when

seancorfield 2021-04-21T20:35:02.315400Z

Gotcha. Yeah, was just reading that over and digesting it. Is into the only transducer that uses a transient? (I’m kinda surprised if that’s the case)

ghadi 2021-04-21T20:36:20.315700Z

it's not the transient that is the issue

ghadi 2021-04-21T20:36:29.315900Z

it's the fracturing of the completion arity

ghadi 2021-04-21T20:37:18.316100Z

it adds metadata and calls persistent! after the call to transduce

ghadi 2021-04-21T20:37:27.316300Z

rather than within the completion arity

seancorfield 2021-04-21T20:37:42.316800Z

@ashnur Not sure I’d recommend it but:

dev=&gt; (defn foo [[&amp; [[k v]]]] (str "key=" k ", val=" v))
#'dev/foo
dev=&gt; (foo {:a 1})
"key=:a, val=1"
dev=&gt; (foo {:a 1 :b 2})
"key=:a, val=1"
dev=&gt; 

Aron 2021-04-21T20:39:14.317600Z

it's more like (foo {"this_is_backend_string_for_multiple_things" [list of related stuff]})

seancorfield 2021-04-21T20:39:15.317700Z

Ah… yeah, that’s a bit subtle…

Aron 2021-04-21T20:39:51.318200Z

I just need it more often to find those things and only once to read it backwards, out of the map

seancorfield 2021-04-21T20:40:45.319Z

You mean {v "this_is_backend_string_for_multiple_things"} kind of destructuring?

ghadi 2021-04-21T20:41:04.319100Z

lmk if I can clarify that in the JIRA

Aron 2021-04-21T20:41:23.319500Z

no, what you wrote is what I need, I just acknowledge that it's weird

Aron 2021-04-21T20:41:52.320200Z

probably with practice and experience I would structure my data differently so that it's easy to read it in both directions

seancorfield 2021-04-21T20:42:23.320800Z

And then there’s

dev=&gt; (defn foo [{v "foo" w "bar"}] (str "v=" v ", w=" w))
#'dev/foo
dev=&gt; (foo {"foo" 42 "bar" :thirteen})
"v=42, w=:thirteen"
dev=&gt; 
just in case anyone wants to destructure on string keys and rename 🙂

seancorfield 2021-04-21T20:43:08.320900Z

No, that makes perfect sense now you’ve explained it.

Aron 2021-04-21T20:45:04.321500Z

btw, this, what just happened, is almost impossible to do in any other language that's commonly used

Aron 2021-04-21T20:45:37.322Z

if I get some nested object and want to read it both ways, I better store it both ways

alexmiller 2021-04-21T20:48:01.322500Z

if you know what the string key is, you can also use :strs (analogous to :keys)

Aron 2021-04-21T20:53:44.324200Z

I found that in the docs, but there is a list of these and only a number of them are present at a time, not all of them, so it makes more sense to iterate over the maps and read the keys than to filter the maps out based on what keys I can find in nested maps

Aron 2021-04-21T20:54:10.324800Z

definitely will use it elsewhere though

Lu 2021-04-21T20:54:43.326Z

Generally, if you provide an input and desired output example you’ll get to the answer you’re looking for much quickly

Aron 2021-04-21T20:55:34.326700Z

dunno, I got the perfect answer in 17 minutes, that's beyond any reasonable expectation imho 😄

❤️ 1
😄 1
Aron 2021-04-21T20:56:07.327200Z

anyone wants quicker solutions, probably have some other issues too 🙂

Alexander Kaiser 2021-04-21T21:04:37.327700Z

@roelof not elegant but maybe a starting point:

(loop
    [spare-counter 0
     strike-counter 0
     scores '(6 4  0 0 10 4 3 0 0 0 0 0 0 8 9)]

  (let [round-result
        (if
         (= 10 (first scores))
          :spare-on-first
          (cond
            (= 10 (second scores))
            :spare-on-second
            (&lt;= 10 (reduce + (take 2 scores)))
            :strike
            )

          )]
    (if
        (or (and (= round-result :spare-on-first)
                 (&lt; (count scores) 1)
                 )
            (&lt; (count scores) 2)
            )
      {:spare-counter spare-counter
       :strike-counter strike-counter}
      (recur ({:spare-on-first (inc spare-counter)
               :spare-on-second (inc spare-counter)
               :strike spare-counter
               nil spare-counter}
              round-result)
             ({:spare-on-first strike-counter
               :spare-on-second strike-counter
               :strike (inc strike-counter)
               nil strike-counter}
              round-result)
             ({:spare-on-first (rest scores)
               :spare-on-second (nthrest scores 2)
               :strike (nthrest scores 2)
               nil (nthrest scores 2)
               }
              round-result)
             )))
  )

roelof 2021-04-22T08:01:03.369200Z

thanks

Alexander Kaiser 2021-04-21T21:05:02.327800Z

Thank you! This helps a lot

Alexander Kaiser 2021-04-21T21:34:42.328100Z

a bit cleaner

(defn frame-length[scores]
  (loop
      [frames []
       scores scores]

    (let
        [round-length
         (if (= (first scores) 10)
           1
           2)
         new-scores (nthrest scores round-length)
         new-frames (conj frames (take round-length scores))
         ]

      (if
          (= (count new-scores) 0)
        new-frames
        (recur
         new-frames
         new-scores
         )))
    )
  )


(def scores '(6 4  0 0 10 4 3 0 0 0 0 0 0 8 9 10))

(frame-length scores)
;;spares
(count (filter #(contains? (set %) 10) (frame-length scores)))
;;strikes
(count (filter (fn[f] (and (&lt;= 10 (reduce + f))
                           (not (contains? (set f) 10))))
               (frame-length scores)))

2021-04-21T22:04:55.336400Z

@roelofw I gave it a shot. Since there is quite a bit of state to care about, I modeled the current state as a map, and put all the rules in a reducing function called roll with arity [state throw] => next-state. The function to get the final state then becomes simply:

(defn game [throws]
  (reduce roll empty-state throws))
A nice thing about this approach is that I can use reductions to get a vector of all the states, which makes it easy to debug. This is my attempt: https://gist.github.com/madstap/d9eb24395841f5a2ee2292ccbd0baec4

Lucas Garcia 2021-04-21T22:16:20.339200Z

Hello y'all! I just started learning clojure and I found some resources about the language, but I was looking for something more focused on web development. Do you have any recommendations? Thanks in advance!

seancorfield 2021-04-21T22:32:57.340Z

Hi @lucas.garcia Have you taken a look at Dmitri Sotnikov’s book on Web Development with Clojure/Script?

Lucas Garcia 2021-04-22T12:58:48.377400Z

Hi, @seancorfield! Thanks for response

Lucas Garcia 2021-04-22T12:59:19.377600Z

I'm checking Dmitri Sotnikov's book right now

Lucas Garcia 2021-04-22T13:00:24.377800Z

I don't know much about web applications, but I have experience with mobile application with flutter and kotlin.

Lucas Garcia 2021-04-22T13:02:18.378Z

I wanted something that could look for when I face any problem.

seancorfield 2021-04-21T22:33:10.340400Z

There’s a 3rd in beta at the moment I believe.

seancorfield 2021-04-21T22:34:48.341300Z

It’s not exactly beginner material, but it will give you an idea of the scope of web development using Clojure on the backend and ClojureScript on the frontend.

seancorfield 2021-04-21T22:35:39.342200Z

If you just want to see a beginner-level example of a (server-side) Clojure web app, I generally point beginners at https://github.com/seancorfield/usermanager-example — and there’s a version using different libraries linked from the README.

seancorfield 2021-04-21T22:36:25.343300Z

It also often helps us point people at appropriate material if they give us a bit of information about their background (amount of programming overall, what languages/tech they’ve used, etc).