This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-03-11
Channels
- # announcements (15)
- # aws (11)
- # babashka (13)
- # babashka-sci-dev (2)
- # beginners (63)
- # calva (20)
- # cider (9)
- # clj-kondo (27)
- # clojars (3)
- # clojure (34)
- # clojure-art (4)
- # clojure-europe (21)
- # clojure-filipino (1)
- # clojure-indonesia (1)
- # clojure-my (1)
- # clojure-nl (11)
- # clojure-norway (10)
- # clojure-sg (1)
- # clojure-spec (4)
- # clojure-uk (4)
- # clojurescript (5)
- # cursive (8)
- # deps-new (2)
- # events (1)
- # exercism (2)
- # fulcro (44)
- # graphql (6)
- # gratitude (1)
- # introduce-yourself (1)
- # jobs (3)
- # leiningen (5)
- # lsp (26)
- # membrane (18)
- # missionary (9)
- # off-topic (1)
- # pedestal (4)
- # portal (1)
- # quil (24)
- # re-frame (17)
- # reagent (5)
- # remote-jobs (2)
- # reveal (3)
- # spacemacs (4)
- # tools-build (1)
- # tools-deps (12)
Hey... design/philosophical question here: Say you have an application-specific data structure T
with special identity semantics. That is, it has some field x
in T
that is irrelevant to its identity, so (= a b)
for a
, b
instanceof T
should disregard the values of x
in a
and b
. If I'm reading https://clojure.org/guides/equality correctly, the only way to achieve that is with deftype
or by actually writing a java class.
So far so good. But what if I need that structure to support clojure's map semantics? I.e. I want to be able to access the fields via keywords and be able to do things like (:x a)
and so on. Then deftype
is out of the question because it can't extend classes, only implement interfaces. So the only remaining option would be some java class along the lines of public class T extends clojure.lang.PersistentHashMap { ... }
. But would that actually work transparently in all cases? I have a feeling there might be weird implications that let it break down in certain contexts. Also, https://clojure.org/reference/datatypes#_why_have_both_deftype_and_defrecord tries to make a rather nebulous argument as to why I wouldn't even want application-specific datatype semantics in general. But custom identity semantics is a thing and if you're dealing with complex data structures it may be an essential tool to achieve proper encapsulation and separation of concerns. Is there some other way I'm overlooking here?
> Then deftype
is out of the question because it can't extend classes, only implement interfaces
But you can extend all the right interfaces to introduce map semantics. There's no real need for inheriting classes here. In fact, it's actually better if your fields are proper members of T
. If I'm not mistaken, that's exactly how records achieve map semantics.
So you're saying I should basically re-implement clojure.lang.PersistentHashMap
? Sure I could, but that'd be pretty much the opposite of sustainable software engineering.
typically in this case you would implement IPersistentMap, not extend PHM
and you can, for example, hold a map as a field and defer most calls to that
yeah, delegating to PHM would certainly be better, but still it increases the maintenance burden if e.g. clojure's relevant interfaces & implementations change.
Not likely that it would, given its history and Clojure’s commitment to not breaking existing things: https://github.com/clojure/clojure/commits/master/src/jvm/clojure/lang/PersistentHashMap.java
This sounds like a great use case for metadata
metadata is defined with the caveat that it doesn't affect equality, so seems like a terrible use case for that
“terrible”, yikes. Or maybe I simply misread the comment after
> That is, it has some field x
in T
that is irrelevant to its identity, so (= a b)
for a
, b
instanceof T
should disregard the values of x
in a
and b
. If I’m reading
and didn’t see that he wants :x
to work as an accessor etc
making this easy is a non-goal - you are strongly encouraged to use the built-in collection types and value equality semantics. if you want something else, that's possible but the burden is on you. there are some libraries like Potemkin that have helpers for creating custom map-like structures
> making this easy is a non-goal - you are strongly encouraged to use the built-in collection types and value equality semantics. if you want something else, that's possible but the burden is on you. Yup, that was my vague impression as well: It's just not a design goal of the language, also due to its heritage. But I'll definitely take a look at potemkin, thanks for the pointer 👍
@U02PSA71D0E what about metadata? You can store fields that don't contribute to equality semantics in the metadata map, and most operations preserve metadata.
It may not work for you, but it may be easier than implementing your own persistent map
I see that suggestion was already discussed.
Hm... making the "irrelevant" fields metadata so they don't contribute to the map's identity... @U064X3EF3 said it's a bad idea, but maybe he interpreted the suggestion differently...? The way you put it, it definitely sounds very interesting.
yeah, if you are just "adding" non-data then metadata is a good use case for that
maybe I was too into the original description
That sounds very much like the "other way" I was overlooking 😁
Hey @U02PSA71D0E , it seems maybe you’ve got your answer for “how”. But I’m curious about the “why”. What kind of structure do you have where equality needs to ignore a field? Could that be modeled as two separate entities? Like you have a
and b
, and others like them stashed somewhere, and then some other structure holds a map of a
to a
’s value for :x
, and b
mapped to b
’s value of :x
. I’m trying to imagine the scenario you’ve described. More details, please.
I'd rather write a separate T=
function, so as not to break existing language semantics. I.e. Don't make equality checks pass, because they're not equal. Rather introduce the new notion of equality, separately.
Does anyone know of a interactive online Clojure repl that allows to load dependencies? I generally use http://repl.it but it seems I can’t load any external libs. I’m looking for something to use for technical interviews
Maybe https://github.com/PEZ/pirate-lang can be useful here. Although I'm not sure why the REPL functionality has to be online for a technical interview.
One more chance to complete the 2022 Clojure Survey!! https://www.surveymonkey.com/r/clojure2022

I am working on an JVM instrumentation library for Clojure which works with Java 9 and up. It doesn't work with Java 8 because it depends on modules that on were only available in tools.jar
prior to Java 9. I just found out my motivating use case has a critical dependency that only supports Java 8. I'm kicking myself for not checking this sooner. Does anyone know of work arounds for detecting the location of tools.jar
in Java 8 and programmatically adding it to the classpath?
I need com.sun.tools.attach.VirtualMachine
and maybe a couple of other things I haven't discovered yet.
Thanks @U42REFCKA and @U3MRWH35M. It looks like URLClassLoader
will do the trick if the jar can be found at that location, right?
One issue I ran into was that the jdk version for tools.jar had to match the jre version it is running for, IIRC.
It would be interesting to hear what exactly are you doing with the tool/library. Perhaps there are existing tools that can solve your problem immediately?
I am attaching an instrumentation agent to the current JVM process. Essentially the same thing done for the "ouroboros" agent of https://github.com/HCADatalab/powderkeg. (https://www.youtube.com/watch?v=OxUHgP4Ox5Q) Then I am using the agent to write class files for all of the in-memory classes created by the Clojure compiler at runtime. The purpose is for distributing work to a remote JVM.
https://github.com/pallet/lein-jdk-tools does exactly this https://github.com/clojure-emacs/enrich-classpath also does it, but also does quite a lot more :) so could be only serve as inspiration (I don't remember if there's any substantial difference between most impls. Most likely not)