beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
2021-02-21T04:43:12.037900Z

hi, can someone explain how this re-gex pattern ways of working work? I tried to

(count (re-seq #"1" "1234554321112345678")) 

;;=> 4 
but if i do this, i got an error
(count (re-seq #(str 1) "1234554321112345678")) 

;;=> Execution error (ClassCastException) at user/eval2152 (REPL:238).
class user$eval2152$fn__2153 cannot be cast to class java.util.regex.Pattern (user$eval2152$fn__2153 is in unnamed module of loader clojure.lang.DynamicClassLoader @32d7ce6f; java.util.regex.Pattern is in module java.base of loader 'bootstrap')
I tried to make function where the 1 as parameter.

dpsutton 2021-02-21T04:49:17.039200Z

re-seq can't take a function in the first position. it must be a regex. and you probably meant #(str %). What you wrote, #(str 1) is a function of zero arguments which will return "1"

2021-02-21T04:54:07.039900Z

@dpsutton yes, i meant #(str %) but it still gives an error

2021-02-21T04:54:48.040200Z

(defn asdf
  [x]
  (count (re-seq #(str x) "1234554321112345678")))

2021-02-21T04:56:58.040500Z

i think i found the answer

(count (re-seq  (re-pattern (str 1)) "1234554321112345678"))

dpsutton 2021-02-21T04:59:51.041700Z

(re-pattern (str 1)) is just (re-pattern "1") which is basically just #"1". you just can't use a function there just the same as you can't add two to a function (+ 1 (fn [] 3))

2021-02-21T05:03:25.043100Z

oh, sorry to be clear, i want to make the number 1 become parameter of a function. sorry for bad english, here's my full code

(defn asdf
  [x]
  (count (re-seq  (re-pattern (str x)) "1234554321112345678"))
*revised

dpsutton 2021-02-21T05:03:59.043500Z

(count (re-seq (re-patter x) ...)

2021-02-21T05:11:22.045400Z

i found that some programmer use ->> macro like this below, is this some preferences or something? does it has an impact to the program? because i still can't do this yet, i only use simple parentheses.

(defn nb-dig [n d]
  ((->> (range (inc n))
        (mapcat #(str (* % %)))
        frequencies)
   (first (str d))))

dpsutton 2021-02-21T05:13:55.046300Z

the extra parens there causes me to do a double take. i'd use a let binding or a (get (->> ...) (first (str d))) to make it a bit more clear what's going on there

devn 2021-02-21T06:37:18.052900Z

@adrianimanuel there’s no impact to the program, it’s just a style choice.

devn 2021-02-21T06:40:13.055500Z

People use it to write something that reads like A.b.c.d instead of (d (c (b A)))

devn 2021-02-21T06:45:11.058300Z

If you want to see the equivalent expression you can do (macroexpand ‘(->> (range 10) (filter even?)))

2021-02-21T06:55:16.062400Z

@devn thank you for the explanation, i got used to (d (c (b A))) since i used ms. excel extensively lol

devn 2021-02-21T07:25:54.064300Z

Excel is a fit predator!

✅ 1
Ilmari Pohjola 2021-02-21T10:51:20.067200Z

Hi! I have a very easy noob question, that I do not find answer by googling. I've got to lists (:x :y :z) and (\x \y \z). I simply want to construct a map {:x \x :y \y :z \z}. Only thing I found was interleave, which unfortunately does not return a map. Any suggestions?

pavlosmelissinos 2021-02-21T10:54:28.067400Z

https://clojuredocs.org/clojure.core/zipmap 😉

Ilmari Pohjola 2021-02-21T10:54:44.067600Z

Cool! Thanks!

bhaim123 2021-02-21T12:50:57.069100Z

Hi, When should I use Java Thread and not Future? (or maybe I should ask, does it matter?) I know that in Future I can wait for the thread to finish and see the return status, and for Java Thread I can’t, right?

bhaim123 2021-02-22T08:49:19.144Z

@alexmiller just to make sure I got it right: The Future is actually using a Java thread pool that Clojure is holding behind the scene? This pool is also used to run the go blocks. The pool default size is the num of processors, but if needed it will be larger?

alexmiller 2021-02-22T14:17:49.161100Z

Yes, Clojure future will run on a Java thread pool in the Clojure runtime Different pool (maintained by core.async) is used to run go blocks The future thread pool can expand without limits but caches unused threads for a while and will reuse if possible

bhaim123 2021-02-22T18:24:36.202800Z

Thank you very much @alexmiller! Now I’ll try to go and understand the core.async thread pool 🙂 any reading material you recommend ?

alexmiller 2021-02-22T19:27:38.208600Z

I mean, it's just a thread pool, not really anything specific to read about that

bhaim123 2021-02-22T19:39:17.208800Z

🙂 Thanks

emilaasa 2021-02-21T13:00:13.069400Z

What are you trying to do?

2021-02-21T13:10:52.069700Z

future : You can use futures to run tasks on a separate thread and then forget about them, but often you’ll want to use the result of the task. The `future` function returns a reference value that you can use to request the result. based on https://www.braveclojure.com/concurrency/ as for javathread, i didn't know bout that yet.

bhaim123 2021-02-21T13:11:46.069900Z

@emilaasa Mainly trying to understand the difference 🙂

alexmiller 2021-02-21T14:27:57.070600Z

Futures run a function on a thread

alexmiller 2021-02-21T14:28:09.071100Z

So they are not that much different

alexmiller 2021-02-21T14:29:00.072700Z

Futures use a cached thread pool though so it can be more efficient if you’re doing this a lot (will reuse the same thread if possible)

bhaim123 2021-02-21T14:30:18.074600Z

Thanks @alexmiller, Will Future run as a Java thread at the end? and the difference is only that Clojure allows to cache the result while in Thread we can’t access it?

alexmiller 2021-02-21T14:30:27.074900Z

Futures also have a useful feature - binding conveyance. The future function runs in an environment where any dynamic bindings are set like they were where you created the future

alexmiller 2021-02-21T14:31:33.076500Z

Yes, futures run on a Thread (all Clojure functions implement Runnable so can be passed directly to a thread)

bhaim123 2021-02-21T14:32:13.076700Z

Thanks, so what is this cached thread pool though that they run on?

alexmiller 2021-02-21T14:32:30.077200Z

It’s one of two in the Clojure runtime

alexmiller 2021-02-21T14:34:31.078Z

The other is for compute only tasks and is a fixed size pool

alexmiller 2021-02-21T14:38:00.079Z

And FYI I wrote a whole chapter about concurrency in Clojure in Clojure Applied with more detail

emilaasa 2021-02-21T15:18:58.079600Z

In my mind a Future is a higher level concept than a Thread as well.

emilaasa 2021-02-21T15:23:07.079800Z

As in the Future represents the result of an operation, whereas a Thread might be the actual lower level construct that could get you that result.

evocatus 2021-02-21T16:44:38.080700Z

hi! getting familiar with clojure.spec. It's great so far. I have a question though

evocatus 2021-02-21T16:44:56.081100Z

How can I write a spec to check if a number is a valid uint64?

evocatus 2021-02-21T16:45:16.081500Z

considering it was fetched from a database column with this type

evocatus 2021-02-21T16:45:49.082Z

looks like Java doesn't support unsigned types (which is a big surprise for me)

evocatus 2021-02-21T16:48:04.082400Z

maybe I should just use nat-int?

seancorfield 2021-02-21T17:28:40.086600Z

@gr.evocatus If it was fetched from the database as a uint64, you may find that is it a BigInt or BitInteger rather than a Long (if it is the latter, it's not going to correctly hold any value larger than Long/MAX_VALUE) -- in which case it won't satisfy nat-int? (because 1234N -- a Clojure BigInt -- does not satisfy int?, but does satisfy integer?).

dev=> (for [pred [int? integer? nat-int? pos-int? neg-int?]
 #_=>       v    [-100N -100 0 100 100N]]
 #_=>   [v (pred v)])
([-100N false] [-100 true] [0 true] [100 true] [100N false] ; int?
 [-100N true] [-100 true] [0 true] [100 true] [100N true] ; integer?
 [-100N false] [-100 false] [0 true] [100 true] [100N false] ; nat-int?
 [-100N false] [-100 false] [0 false] [100 true] [100N false] ; pos-int?
 [-100N false] [-100 true] [0 false] [100 false] [100N false]) ; neg-int?

2021-02-21T17:59:23.087400Z

You can interact with a thread while it runs in semi-arbitrary ways while it runs, I believe. One of the things about a future is you are effectively saying "I don't care to interact with you at all, except for you to tell me when you are done, and what result you got"

2021-02-21T17:59:49.087600Z

You could start a thread and pass messages / intermediate results back and forth N times, or indefinitely.

2021-02-21T18:00:32.087800Z

I could be off on this -- but I suspect at least most futures are created in a context that have the "limited interaction" I mention above.

bhaim123 2021-02-21T18:51:00.088100Z

Thanks everyone! I think it is time for to go and read @alexmiller chapter 🙂

alexmiller 2021-02-21T19:14:59.088600Z

well I disagree that a future may only care about the result (but that is the primary use case). I've certainly used futures to background an operation that interacted with the original thread more than once via promises.

grazfather 2021-02-21T19:39:34.089Z

what does clojure-lsp offer over everything in Cider?

dpsutton 2021-02-21T19:43:54.091200Z

clojure-lsp offers high quality static analysis that does not depend on a running instance of your code. this means that it can do quite a bit without running things, but it can miss things that are only apparent with an actual running instance: macros which expand to forms, run time requiring, loading of things, etc. CIDER runs in your project and can basically query all of this stuff from the repl, much like a clojure repl provides. (eg, ns-publics, doc, info, ...)

dpsutton 2021-02-21T19:44:54.092500Z

they can be quite complementary. a standout from the analysis is the clojure-lsp will perform refactorings on your code, introduce lets, extract functions, rename things, etc. CIDER can accomplish this with an extra refactor-nrepl dep, but i don't believe its quite at the level of what clojure-lsp can do

borkdude 2021-02-21T19:48:04.092700Z

yes, they are complimentary, I would not want to program without a REPL / CIDER, however in CLJS I hardly ever use a REPL because that's too much friction for me. I rely entirely on hot-reloading (figwheel) there or for node projects I just call require + :reload from a nodeJS REPL in my terminal. So clojure-lsp now provides navigation in CLJS whereas before I didn't have this at all for a long time

borkdude 2021-02-21T19:48:49.093500Z

one feature that I believe CIDER (and maybe even Cursive?) doesn't have is finding keyword references. I demonstrate this in a Youtube video I made yesterday, towards the end.

borkdude 2021-02-21T19:49:12.094100Z

e.g. it can find references to :clojure.string/foo even if you write it as ::str/foo

evocatus 2021-02-21T20:04:00.095800Z

can I write a spec to check some complex conditions like "values of map ::total are sums of values of the same keys of maps inside ::rows"?

robertfw 2021-02-21T20:06:09.097200Z

@gr.evocatus You can write your own predicates, so you can write specs that check just about anything. I don't quite understand the data structure you are describing so can't go into more depth about how you might want to accomplish that

evocatus 2021-02-21T20:09:56.098200Z

But how do I do it? Just something like this? (s/def ::reply (s/and (s/keys :req [::rows ::total]) #(some-complex-checks)))

robertfw 2021-02-21T20:11:19.099200Z

yup. note that if you want to be able to generate values using (s/gen) you'll need to provide your own generator with s/with-gen

👍 1
2021-02-21T20:24:10.100Z

Is it possible to make an extend-type for PersistentHasMap and PersistentArrayMap in one go?

2021-02-21T20:24:29.100300Z

it's basically the same thing

dpsutton 2021-02-21T20:28:20.100600Z

(extend-protocol Foo
  clojure.lang.APersistentMap
  (f [_] :foo-on-map))
worked for me

dpsutton 2021-02-21T20:28:46.101Z

(f {}) and (f (into {} (map (fn [x] [x x])) (range 1000))) both return :foo-on-map

2021-02-21T20:28:57.101200Z

thx!

alexmiller 2021-02-21T21:21:24.101800Z

You really should not be extending the Clojure concrete types like that - much better to make your protocol extensible via metadata

2021-02-21T21:23:20.103100Z

I heard something somewhere about metadata, so I'm going to go read more

2021-02-21T21:24:21.104300Z

Can I find anything beyond that? https://clojure.org/reference/protocols#_extend_via_metadata

alexmiller 2021-02-21T21:25:19.105100Z

(defprotocol Foo :extend-via-metadata true (f [_]))
(defn decorate-map [m] (with-meta m {`f (fn [_] :foo-on-map)}))
(f {:a 1}) ;; error, no impl
(f (decorate-map {:a 1})) ;; :foo-on-map

alexmiller 2021-02-21T21:25:26.105400Z

that's all there is to it

alexmiller 2021-02-21T21:26:03.105600Z

also read the section right above that - https://clojure.org/reference/protocols#_guidelines_for_extension

alexmiller 2021-02-21T21:28:00.107700Z

types like APersistentMap, PersistentHashMap, PersistentArrayMap should be considered concrete implementation details inside of Clojure, not public APIs you can rely on, so you should really never be extending protocols to them. IPersistentMap is the proper generic interface, but even that I would be hesitant about as protocol extension on interfaces can open you up to diamond inheritance resolution issues

seancorfield 2021-02-21T21:32:39.109800Z

@huxley One of the things that is really nice about extending protocols via metadata is that you can use anything that supports metadata, such as a Clojure function. In next.jdbc, it provides a function to support Stuart Sierra's Component library for creating database connection pools, and it uses a function (that returns the pool) with metadata to implement Component's stop function: https://github.com/seancorfield/next-jdbc/blob/develop/src/next/jdbc/connection.clj#L287-L318

2021-02-21T21:38:07.110100Z

I'm going to start reading

2021-02-21T21:38:08.110300Z

thx

grazfather 2021-02-21T21:53:27.110400Z

awesome thank you (and ty borkdude, too)

dpsutton 2021-02-21T21:55:27.110600Z

just FYI he is the author of the fantastic static analysis tool