beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
Eddie 2021-04-30T01:06:02.261900Z

I’m failing to find a documented example of a return type-hint + a docstring on a function. The compiler tells me this is wrong:

(defn foo ^Long
  "I do nothing" 
  [^Long x] x)

;; Syntax error: Metadata can only be applied to IMetas
It compiles if the type hint is moved after the docstring, but I’m not sure if that is annotating the correct thing. Any advice for dong this right?

alexmiller 2021-04-30T01:06:51.262600Z

That’s correct - it goes before the arg vector

🙏 1
Eddie 2021-04-30T01:08:24.263Z

Gotcha. Thanks @alexmiller!

Michael Lan 2021-04-30T02:05:35.263700Z

where’s the log for this slack?

2021-04-30T08:51:27.270Z

Whoa. Nice. For some reason I earlier just assumed information was gone, unless I captured it somehow. Didn’t occur to me someone was saving things. Things I learn. 🙂

seancorfield 2021-04-30T17:24:57.281600Z

@mattias504 look for either @logbot and/or @zulip-mirror-bot in a channel. If they’re there, messages are being saved. If not, you can /invite them to a channel and new messages from that point will get saved.

Edward Ciafardini 2021-04-30T03:30:55.265800Z

Going through the Reagent documentation and an example is provided for updating state using "on-change" for an input.

(ns example
  (:require [reagent.core :as r]))
(defn atom-input [value]
  [:input {:type "text"
           :value @value
           :on-change #(reset! value (-> % .-target .-value))}])

(defn shared-state []
  (let [val (r/atom "foo")]
    (fn []
      [:div
       [:p "The value is now: " @val]
       [:p "Change it here: " [atom-input val]]])))
This mostly makes sense to me, but I am struggling picking apart this specific line:
:on-change #(reset! value (-> % .-target .-value))}])
Searching the web for "->" and ".-" has not yielded great results as you might imagine

Michael Lan 2021-04-30T03:37:32.266300Z

Thank you!

seancorfield 2021-04-30T03:37:34.266500Z

The former is purely a readonly searchable index/log. The latter is also a chat community, that has a one-way mirror of nearly all channels here and is searchable with no limits (because it is on Zulip’s free open source plan).

seancorfield 2021-04-30T03:38:33.267300Z

.-foo is a JavaScript field selection in ClojureScript. -> is the “thread first” macro.

👍 1
seancorfield 2021-04-30T03:39:01.267600Z

@esciafardini You’ll probably find this helpful: https://clojure.org/guides/weird_characters

seancorfield 2021-04-30T03:41:17.268800Z

(-> % .-target .-value) will macroexpand to (.-value (.-target %)) if that helps: get the target field from the anonymous function’s argument, and then get the value field from that.

seancorfield 2021-04-30T03:41:44.269200Z

(you may also find the #reagent channel helpful, if you’re not already a member)

valerauko 2021-04-30T09:04:57.272300Z

I made a namespace that should generate a java class with (:gen-class This worked all right until I made an edit to the namespace in question. Since then (even if I revert the changes to the code that worked earlier) lein just refuses to aot it anymore, giving me java.lang.ClassNotFoundException What can cause this?

valerauko 2021-04-30T09:05:29.272700Z

I've tried the "usual" candidates like clearing target and even wiping my .m2

valerauko 2021-04-30T09:22:10.273400Z

Even if I explicitly try to run lein compile app.class-namespace

valerauko 2021-04-30T09:42:00.273800Z

Hmm it finally re-compiled it once I removed every reference to the class from other places in the source first

Juλian (he/him) 2021-04-30T10:07:16.274400Z

is there a way to test side-effects of functions, for example the output of println? or should I make the function return the string instead of printing and call println with on the result of the function?

2021-04-30T10:10:28.274600Z

(with-out-str (fn-with-side-effects)) ;; => "printed string"

2021-04-30T10:11:46.274800Z

but I would try to avoid side effects as much as I can. so return a string to be printed sound right for me

Juλian (he/him) 2021-04-30T10:14:14.275Z

it's a text based game, so printing is an essential part of it 😅

Juλian (he/him) 2021-04-30T10:14:27.275200Z

but thanks for the answer

2021-04-30T10:17:21.275400Z

I don’t meant to say “avoid it completely” ) I should say “keep it as far from core functionality as possible”.

Juλian (he/him) 2021-04-30T11:36:41.275800Z

just had a thought during my lunch run.. maybe I want to reuse the code for a different interface, for example a webpage. that would be easier then, too. thanks for the hint

2021-04-30T13:35:49.276400Z

Hey everyone, I am looking to dissoc some keys from a list of maps. How do I go about passing the current iteration of a map function to a dissoc?

(def final-map (map (dissoc <I need the current iteration here>[:uselessKey1 :uselessKey2]) (vals items)]))

2021-04-30T13:38:41.277200Z

You want an anonymous function there: (def final-map (map #(dissoc % :uselessKey1 :uselessKey2) (vals items)]))

🙌 1
2021-04-30T13:40:05.277700Z

(Also no square brackets around the keys you want to dissoc from the map)

2021-04-30T14:02:32.278200Z

What is the significance of # in this context? I see this a lot in Clojure but can't find a doc for this. What is the terminology?

2021-04-30T14:12:58.278400Z

That’s one of the two ways of writing an anonymous function. It’s basically just a shorthand way to throw together a quick anonymous function for use with things like map and filter and reduce and so on.

2021-04-30T14:14:13.278600Z

The % means the first arg to the function, and if you have more args than that, the second arg is %2 and the third is %3 and so on.

2021-04-30T15:27:14.278800Z

it is often recommended in designing clojure programs to have a pure core and then a "runner" that performs the side effects. There are some really great talks about this: https://www.youtube.com/watch?v=ZQkIWWTygio https://www.youtube.com/watch?v=JvGXyNXky0Q see also, re-frame's dispatch

pithyless 2021-04-30T16:55:17.279100Z

I think this talk was also pretty good about strategies on how to pull apart effects from the rest of your codebase: https://www.youtube.com/watch?v=IZlt6hH8YiA

Prabu Rajan 2021-04-30T16:59:22.281100Z

Hi, which of the following for this is a better option? Are there any better than these?

;; option 1
(defn update-user [users id user]
  (update-in users [id]
             #(if (nil? %)
                (throw (IllegalArgumentException. (str "User " id " does not exist")))
                user)))

;; option 2
(defn update-user-contains [users id user]
  (if (contains? users id)
    (assoc-in users [id] user)
    (throw (IllegalArgumentException. (str "User " id " does not exist")))))

(update-user
 {:one {::first-name "Agatha" ::last-name "Christie" ::email "<mailto:agatha.christie@mail.com|agatha.christie@mail.com>"}}
 :two
 {::first-name "Prabu"
  ::last-name "Rajan"
  ::email "<mailto:prabu.rajan@mail.com|prabu.rajan@mail.com>"})

2021-04-30T17:01:04.281200Z

Second will have nicer stacktrace

Prabu Rajan 2021-04-30T17:09:26.281400Z

I agree. I prefer the 2nd one too in terms of simplicity. I was just wondering in terms of performance, which one would be better, but it turns out that both take almost similar time, but I have not really measured it for large maps

Franco Gasperino 2021-04-30T18:09:57.282600Z

what is the preferred idiom of using a defn- vs a letfn. I understand the scope, but asking for style

alexmiller 2021-04-30T18:11:31.283100Z

In general, I think top-level functions should be defn-

alexmiller 2021-04-30T18:11:48.283500Z

letfn is mostly useful inside functions, particularly when making something recursive

alexmiller 2021-04-30T18:12:02.283900Z

kind of for "functions private to a function"

alexmiller 2021-04-30T18:12:23.284700Z

but generally even for things like that, I mostly just make defn- as they are easier to test, doc, etc

NoahTheDuke 2021-04-30T18:12:30.284900Z

letfn is also good for closing over local variables without having to pass them in

Franco Gasperino 2021-04-30T18:18:11.287500Z

both of those answers are appreciated

Audrius 2021-04-30T19:24:25.288Z

Hi, what are Clojure editor usage statistics?

dpsutton 2021-04-30T19:26:12.288400Z

second graph in that section

dpsutton 2021-04-30T19:27:02.289300Z

note this is not a true editor usage statistics but editor usage statistics of people who responded to the state of clojure survey. Hopefully it is representative of the community at large but that's not a certainty

alexmiller 2021-04-30T19:28:55.290100Z

it's ~2500 responses so probably a good enough sample (tracks with prior years)

piyer 2021-04-30T19:46:23.291500Z

Looking to find the clojure docker image to run in production. I found https://github.com/Quantisan/docker-clojure/blob/99e09867b734efda57f117a1a266bcb2dce25a33/target/openjdk-11-buster/lein/Dockerfile, is there a tag without lein? or what is the recommended version?

ghadi 2021-04-30T19:49:53.292400Z

@munichlinux my standard procedure is to build a jar then put it in a plain JDK container

ghadi 2021-04-30T19:50:14.292900Z

I never ship lein to prod

piyer 2021-04-30T19:50:32.293500Z

that is what I was expecting to do.

ghadi 2021-04-30T19:51:02.294200Z

clojure is "just a library"

ghadi 2021-04-30T19:51:15.294700Z

my prod containers call java -cp the.jar clojure.main -m my.entrypoint.namespace as entrypoint

piyer 2021-04-30T19:51:27.295100Z

I thought there is some version with just jdk 11. I guess I should look in the openjdk docker.

ghadi 2021-04-30T19:51:56.295600Z

adoptopenjdk or corretto are my goto containers

piyer 2021-04-30T19:54:24.295800Z

Nice https://hub.docker.com/r/adoptopenjdk/openjdk11/ has alpine.

piyer 2021-04-30T19:54:34.296100Z

@ghadi Thank you.

ghadi 2021-04-30T19:55:15.296400Z

fyi alpine isn't "official" until after 11

ghadi 2021-04-30T19:55:32.296800Z

(I think, JDK 14 gave real support for it?)

ghadi 2021-04-30T19:55:55.297200Z

everyone uses it, but YMMV

ghadi 2021-04-30T19:56:29.297900Z

right -- the JDK didn't officially support Alpine in 8 or 11

ghadi 2021-04-30T19:57:25.298900Z

some people still put together artifacts for alpine -- just not supported

piyer 2021-04-30T19:58:08.299200Z

I see, what would you recommend?

piyer 2021-04-30T19:58:21.299400Z

I also see debian.

ghadi 2021-04-30T20:00:34.299800Z

the debian based one is fine

ghadi 2021-04-30T20:00:42.300200Z

if you want alpine you should use latest (16)

piyer 2021-04-30T20:01:16.301100Z

ya, clojure LTS says it supports 11.

ghadi 2021-04-30T20:01:16.301200Z

and look into jlink , which is a better way of stripping down a JVM for smaller artifact sizes

piyer 2021-04-30T20:01:31.301400Z

will do