Fork me on GitHub
#clojure
<
2019-08-05
>
metacritical04:08:49

@hiredman :thumbsup::skin-tone-2:

meguru11:08:27

Hello. Do you know any example about web push using clojure? I found the library ”web push-clojure” but I want to know any example about this.

jaihindhreddy12:08:54

In this code:

(def a ["a" "b" "c" "d" "e" "f" "g"])
(def b (assoc a 3 42))
(identical? (first a) (first b))
; => true

jaihindhreddy12:08:28

Does Clojure guarantee they'll be identical? Does Clojure's current impl of vector guarantee they'll be identical?

jaihindhreddy12:08:29

I guess what I wanted to ask is, does assoc'ing something onto a vector of size n produce something that always shares at least n-1 things with the original vector?

jaihindhreddy12:08:16

Or are there cases when less things are shared?

Alex Miller (Clojure team)12:08:36

the values in the vector will all be identical except the one you replaced

Alex Miller (Clojure team)12:08:45

what else could they be?

jaihindhreddy16:08:39

I'm not questioning whether assoc works. I'm wondering whether each leaf node in the HAMT has only one thing, and will never be copied as part of the path copying required to make the new vector.

andy.fingerhut16:08:25

If you are asking about the current implementation, it does not make copies of objects like that, that I am aware of. A counter-question for you: When would you care, except for performance?

andy.fingerhut16:08:07

I am not saying that performance is unimportant -- it definitely is important. It is just that if you are asking because you want to write code that relies upon things being identical? or not, I would advise against doing that, in most cases.

jaihindhreddy16:08:34

Performance was my concern. For vectors which contain very large things, copying even one thing as part of an assoc or a conj might be too expensive. Definitely intending to program with values as much as possible.

andy.fingerhut16:08:36

I have looked through several of the Clojure implementations, and while you can find plenty of code for cloning 32-element arrays that are used as tree nodes, I have never seen any calls that try to 'clone' or copy the elements of the collection, when those elements are general Object type. There is no general clone method that is guaranteed to do anything useful across all Java objects, I don't believe.

💯 4
andy.fingerhut16:08:52

There is a Clojure class of vectors restricted to primitive elements, and that one can copy arrays of 32 primitives when assoc/conj calls are done, but in that case, the whole point is to save memory and improve performance by limiting itself to all elements of one primitive type. This is the implementation of the vectors returned by the function vector-of.

andy.fingerhut16:08:06

If you would like to explore some low level implementation details of Clojure data structures as they exist in memory, for Clojure on Java, there is this library I wrote that can help visualize the data sharing that occurs. In particular, the 'More example' section of the README has some sample code to color-highlight two HAMT's with different colors for data that is unique to one, or unique to the other, or shared: https://github.com/jafingerhut/cljol

💯 4
borkdude18:08:55

I've made a JSON -> EDN tool and now someone asks about the case when you use key with spaces in JSON and keywordize them in EDN, you get something like this: {"foo bar": 1} -> {:foo bar 1} which is invalid EDN. I bet someone has thought of a solution regarding this before?

borkdude18:08:43

there are multiple solutions. one of them is to encode the space somehow, but it might not always that this is what users want

noisesmith18:08:21

you could use string keys, or even emit (keyword "foo bar")

noisesmith18:08:43

I guess edn/read would give you a useless list for that, so never mind

borkdude18:08:44

but that EDN should also be able to be read back in

noisesmith18:08:11

string keys avoid the problem, at the cost of people not liking it

noisesmith18:08:13

can transit handle a space in a keyword?

borkdude18:08:20

yes, it can

Alex Miller (Clojure team)18:08:52

I suspect the best answer depends on the context and all of those possible solutions are best in some context

dominicm19:08:45

Unrepl has a solution to this

Lennart Buit19:08:02

that makes me wonder, what do you do with EDN values that have no JSON representation? That is an equally destructive operation right?

Lennart Buit19:08:46

like, what happens when you are converting {:a 9007199254740992} (maximum int fitting in a float continuously plus one) from EDN -> JSON

zane20:08:28

Is there an easy way to call the constructor for a class that you have the value for at runtime?

zane20:08:40

I imagine I need clojure.reflect.

noisesmith20:08:44

it might be easier to just use eval for something like that

zane20:08:23

clojure.lang.Reflector/invokeConstructor seems to do the trick, but I believe is internal.

ghadi20:08:25

"What are you trying to solve?"

ghadi20:08:48

there's no generic way to re-call a constructor for an arbitrary thing @zane

zane20:08:04

Great question.

ghadi20:08:04

I doubt you're working with arbitrary things, though

zane20:08:11

I'm trying to call the constructor for a class if it's available on the classpath.

zane20:08:31

I figured I'd use reflect/resolve-class to test for its presence.

ghadi20:08:55

so you have an object, then you get its class?

ghadi20:08:11

what if there are 5 constructors?

zane20:08:23

It's not an arbitrary class.

zane20:08:04

It's a specific class (`javafx.embed.swing.JFXPanel`) that may or may not be on the classpath depending on version of Java being used to run the program.

noisesmith20:08:05

why not

user=> (if (try (Class/forName "Foo") (catch ClassNotFoundException _)) (eval '(Foo. x y)) :nope)
:nope

ghadi20:08:42

eval + delay

zane20:08:45

Yeah, eval would work for sure. I'm just wondering whether there's a better way.

zane20:08:00

You'd say that's preferable to Reflector/invokeConstructor?

zane20:08:36

Right on.

noisesmith20:08:36

@zane does this help?

user=> (.newInstance (Class/forName "java.util.Date"))
#inst "2019-08-05T20:55:21.354-00:00"

zane20:08:22

Oh, interesting. .newInstance is new to me.

ghadi20:08:46

(def my-thing (delay (eval '(some giant form))))

ghadi20:08:00

with conditionals around the argument to eval if you need 'em

noisesmith20:08:24

only works with nullary constructors

ghadi20:08:32

.newInstance is deprecated

ghadi20:08:35

don't use it

4
noisesmith20:08:57

good to know

ghadi20:08:36

(delay (eval (if (>jdk8?) '(jdk11 form) '(jdk8 form...))))

Alex Miller (Clojure team)21:08:17

rather than checking a jdk version, it is much better to check for the existence of a class before using it

zane21:08:46

That makes intuitive sense to me. Do you generally do that via Class/forName, or some other method?

ghadi21:08:23

Steal when-class from clojure core

zane21:08:49

Yep! That's basically how I implemented it by hand.

zane21:08:49

@U064X3EF3 Would you extend that to static class methods that were added with a specific version? That is to say, would you recommend checking for the existence of the specific method I want to use?

Alex Miller (Clojure team)21:08:35

I think that would be analogous

Alex Miller (Clojure team)21:08:55

"before I use a thing that may not exist, check that it exists"

Alex Miller (Clojure team)21:08:14

trapping an exception in the failure case might be another option in some cases

zane21:08:41

Got it. This is really helpful. And the way you'd recommend to check for the presence of a specific method would be via clojure.reflect/reflect?

Alex Miller (Clojure team)21:08:32

as that's much less likely to break than version checking

Alex Miller (Clojure team)21:08:52

(having debugged my share of buggy java version check conditionals)

chrisulloa23:08:42

Does anyone know if you can type hint an argument of a type created by gen-class?

chrisulloa23:08:22

(gen-class :name model.Message) (defn some-func [^model.Message msg] ...)

chrisulloa23:08:25

Oh nevermind I guess I can, maybe this is better for cursive channel because it’s complaining that the class can’t be found… which makes sense since if it’s not compiled