clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
Nazral 2021-07-03T01:28:04.311400Z

Hello, we cannot push libraries to clojars under libraryname/libraryname anymore? (sorry if this is not the proper channel to ask this)

lread 2021-07-03T20:49:25.340600Z

fwiw, there is also the #clojars channel if you have more questions on clojars.

phronmophobic 2021-07-03T01:44:05.311500Z

Here's an FAQ that covers some of the rationale https://github.com/clojars/clojars-web/wiki/Verified-Group-Names

Nazral 2021-07-03T01:45:18.311700Z

Ok thank you!

phronmophobic 2021-07-03T01:46:08.311900Z

per https://github.com/clojars/clojars-web/wiki/Verified-Group-Names#how-does-this-impact-existing-libraries-published-to-clojars, I thought it shouldn't impact new versions of existing libraries. Is this a new library?

phronmophobic 2021-07-03T01:49:53.312100Z

I think the main idea is to make clojars more secure and the clojars team has been proactive about supporting a better approach.

Nazral 2021-07-03T01:52:43.312300Z

It is a new library yes, that's why it caught me off guard, I have no problem with the requirement I was just surprised I couldn't simply deploy anymore 😛

👍 1
1
seancorfield 2021-07-03T02:10:47.312700Z

I've changed the group ID of my most popular libraries to satisfy the VGN policy (from seancorfield to com.github.seancorfield) and all my READMEs link to the Clojars wiki (and my CHANGELOGs explain the group ID change).

seancorfield 2021-07-03T02:11:28.312900Z

antq seems to detect old groups/new groups so it can recommend upgrading a library across the group ID change, which is really nice.

👍 1
2021-07-03T06:43:53.315500Z

I know the read-eval is frowned upon, but out of curiosity, can someone explain the semantic context of what it evals? Shouldn't one of these work?

(def foo 1)
#=foo
#='foo
#=(deref (resolve foo))

p-himik 2021-07-03T07:33:10.316200Z

Perhaps you already know what follows and are interested only in why evaluation in the context of read and read-string is different from eval. Alas, I don't know the answer to that, and I can only describe the difference itself. Evaluation done by read and read-string is very limited and supports only the following cases: • The form is a symbol naming a Java class, (read-string "#=java.lang.String") • The form is a list and the first symbol is a symbol ◦ that is var and the next one is a fully qualified symbol, (def x) (read-string "#=(var user/x)") ◦ that denotes a constructor calling, (read-string "#=(java.lang.String. \"x\")") ◦ that denotes a static member calling, (read-string "#=(java.lang.Integer/parseInt \"1\")") ◦ that names something in the current NS, and the rest are quoted entities, (read-string "#=(inc 1)") As you can see, everything after the first symbol is left untouched - foo in your example is just a symbol and (resolve foo) is just a list. This makes read[-string] eval extremely limited by itself in comparison to eval, but you can use eval there to circumvent that: (def x 1) (read-string "#=(eval x)")

👏 1
👌 1
2021-07-03T07:48:29.316700Z

That's exactly what I wanted, thanks!

william 2021-07-03T14:01:07.318200Z

Is there a clojure/cljs formatting tool that splits long lines in the code?

takis_ 2021-07-03T14:30:10.319Z

Hello is there a way to get the symbol/number/strings (all the literal parts) from a nested form that can contain any type of form ?

(get-members (assoc {"a" (:a m)
                     "b" #{"a" "b" (f 1 2)}})) 

To return something like 

[assoc "a" :a m "b" "a" "b" f 1 2]

dpsutton 2021-07-03T14:34:30.319800Z

Looks like a depth first walk through a tree

dpsutton 2021-07-03T14:34:53.320400Z

And it’s possible depending on if you have access to the form itself.

dpsutton 2021-07-03T14:35:40.322500Z

If you have access to the actual form it’s fine. There are also some tricks that you can do with metadata if you don’t have access to the form as data. Macros like source do some neat tricks

takis_ 2021-07-03T14:36:10.323Z

is there a standard way to do it? i can access the form,for example get-members could be a macro,and parse the form

2021-07-05T15:54:13.365100Z

I think this is pretty standard

user=> (filter (complement coll?) (tree-seq coll? seq '(assoc {"a" (:a m) "b" #{"a" "b" (f 1 2)}})))
(assoc "a" :a m "b" "a" "b" f 1 2)

2021-07-05T15:54:39.365300Z

you could use a fn instead of complement but I'd be suspicious of any solution other than a filter / tree-seq combo

takis_ 2021-07-03T14:36:38.323500Z

but i was wondering if there is a standard library i can use for this

Søren Sjørup 2021-07-03T14:37:27.323800Z

sun

dpsutton 2021-07-03T14:38:28.325100Z

Yeah check out tree-seq for getting the nodes. Gives you a depth first lazy sequence of the nodes of the tree. You could also just walk it yourself

takis_ 2021-07-03T14:39:20.325300Z

thank you dpsutton : )

quoll 2021-07-03T15:06:09.327Z

This looks like you want flatten but working on maps as well. That’s a small change from the defn for flatten to use seqable? instead of sequential?:

(defn flatten2
 [x]
 (filter (complement seqable?)
         (rest (tree-seq seqable? seq x))))

quoll 2021-07-03T15:10:57.327200Z

My first thought was to use flatten, but I’d never tried it on maps before, and I discovered that it didn’t work. So I looked at the source to flatten, saw that it did the tree-seq (good call @dpsutton!) but used sequential?, which maps don’t match.

borkdude 2021-07-03T15:11:54.327500Z

That will also screw with string keys/values btw:

user=> (flatten2 {:a "foo"})
(:a \f \o \o)

👍 1
borkdude 2021-07-03T15:13:20.327700Z

perhaps coll? is a better default than seqable?

💯 1
borkdude 2021-07-03T15:13:32.327900Z

(I just checked, it also returns true for MapEntry...)

👍 1
vemv 2021-07-03T15:14:16.328200Z

zprint

quoll 2021-07-03T15:15:26.328400Z

Cool. 🙂

quoll 2021-07-03T15:16:19.328600Z

Yes, I’m rushing about like a headless chook right now (family is yelling at me to get out the door). It’s a terrible time to try to write a bit of code :rolling_on_the_floor_laughing:

borkdude 2021-07-03T15:17:28.329Z

seqable? + strings is a common pitfall, I wish it didn't handle strings most of the time

takis_ 2021-07-03T15:25:10.329800Z

i used postwalk,seems to do what i need

quoll 2021-07-03T15:33:34.332500Z

While it may be a “gotcha”, I appreciate being able to process strings as seqs. And seqable? is the function that tells us that we can do that. So I like it as-is. I just have to remember not to do silly things 🙃

quoll 2021-07-03T15:34:28.332800Z

(If only…)

borkdude 2021-07-03T15:38:19.333100Z

It's sometimes not recommended to treat strings as seqs if you want performance, but this isn't always important.

👍 1
borkdude 2021-07-03T15:45:58.334200Z

@takis_ fwiw, we had a conversation about your question in a thread, not sure if you missed that ;)

william 2021-07-03T16:31:05.334400Z

thank you @vemv!

🙌 1
vlaaad 2021-07-03T16:37:52.334700Z

Usually I use (constantly nil) for 1-arg noop functions, but recently I realized I can use {} for that 🤯

2021-07-03T16:47:34.334800Z

#(#_ %)
another mind bending variant )

2
vlaaad 2021-07-03T17:32:41.336Z

What the...

borkdude 2021-07-03T17:33:33.336200Z

I did some serious benchmarking using dotimes and came to the scientific conclusion that #{} is objectively better.

user=> (time (dotimes [i 100000000] ({} :foo)))
"Elapsed time: 317.749149 msecs"
nil
user=> (time (dotimes [i 100000000] (#{} :foo)))
"Elapsed time: 274.513781 msecs"
nil

👍 1
borkdude 2021-07-03T17:37:25.336500Z

But probably nothing beats...

user=> (time (dotimes [i 100000000] ((fn [_]) :foo)))
"Elapsed time: 55.271143 msecs"

takis_ 2021-07-03T18:04:23.338Z

yes i saw it, thank you trying to help. postwalk worked,it does what i want at least for what i tested, i didnt want to try something mine and have un-expected bugs

2021-07-03T20:31:08.338200Z

In ClojureScript, {}seems to beat event (fn [_])in my very similarly thorough benchmarks

2021-07-03T20:34:02.340300Z

This might be the best contributor patch I ever saw to Clojure: https://clojure.atlassian.net/browse/CLJ-2637

p-himik 2021-07-03T20:35:38.340400Z

A desktop link: https://clojure.atlassian.net/browse/CLJ-2637

borkdude 2021-07-03T20:51:44.340800Z

hmm, I can't repro that e.g. in http://klipse.app:

(time (let [x {}] (dotimes [i 10000000] (x :foo))))
(time (dotimes [i 10000000] ({} :foo)))
(time (dotimes [i 10000000] (#{} :foo)))
(time (dotimes [i 10000000] ((fn [_]) :foo)))
(time (let [x (fn [_])] (dotimes [i 10000000] (x :foo))))
"Elapsed time: 498.400000 msecs"
"Elapsed time: 573.200000 msecs"
"Elapsed time: 805.800000 msecs"
"Elapsed time: 93.700000 msecs"
"Elapsed time: 208.500000 msecs"

borkdude 2021-07-03T20:52:10.341Z

The (time (dotimes [i 10000000] ((fn [_]) :foo))) is the fastest of the bunch there

borkdude 2021-07-03T20:58:05.341200Z

I would have expected (time (let [x (fn [_])] (dotimes [i 10000000] (x :foo)))) to be faster, but perhaps the JS engine optimizes it differently..?

borkdude 2021-07-03T20:59:10.341400Z

Clojure JVM emits one global function object per anonymous function expression, i.e. it doesn't create new functions in a loop, it re-uses the one global function and passes parameters as needed

borkdude 2021-07-03T21:00:11.341600Z

but CLJS emits JS source code, which is obviously different

2021-07-03T21:16:51.342800Z

Interesting, I tested it on Replete android self-host cljs repl app 😜

2021-07-03T21:18:50.343500Z

Ya changed my link to that, much better

quoll 2021-07-03T21:25:46.349600Z

I was curious about the timing of #{} vs. {} since PersistentHashSet wraps a PersistentHashMap. However, {} is a PersistentArrayMap and even when it’s empty it goes through several calls to determine that something isn’t in it. It’s wasteful, but I also don’t think it’s used enough for anyone to consider it being worth optimizing