Hi there! I am trying to implement my own set-esque data type that has all the set semantics but the implementation is very different. I was wondering if I could use the pre-made clojure.set functions with my set (like union, etc.) but I can see they are not members of any protocol (or do not seem to be). I can see that internally union uses only count, conj, next and first, and I could easily provide an implementation for those. But again, count for example doesn't seem to be a member of clojure protocol, with the implementation pointing me towards clojure.lang.RT/count and that points to a java interface "Counted". Therefore, the chance of being able to use the default clojure methods seems to be low - am I right on that or is there a way to find some internal clojure protocols? Or maybe I could create a new protocol that could override the default implementation of 'count', etc. somehow? will the "union" from clojure.set be able to pick it up automatically?
@mll Clojure itself is based on Java interfaces, so you can create new types in Clojure that implement the various Java interfaces liked Counted
etc and then the various core functions will all work on it.
Ok, so you suggest @seancorfield that I should focus on implementing java interfaces and not use the "defprotocol" for this one at all?
Depending on how close it needs to be to Clojure's set data structure, you'll need to implement some subset of this lot:
user=> (ancestors (type #{1 2 3}))
#{clojure.lang.IEditableCollection java.util.Set java.util.concurrent.Callable java.lang.Runnable clojure.lang.IPersistentSet clojure.lang.Counted clojure.lang.Seqable java.io.Serializable clojure.lang.IObj clojure.lang.IFn java.lang.Iterable clojure.lang.IHashEq clojure.lang.APersistentSet java.util.Collection clojure.lang.AFn clojure.lang.IMeta java.lang.Object clojure.lang.IPersistentCollection}
but, as you've seen, sets mostly support basic operations like count
(`Counted`) so as long as your type responds correctly to those, your set implementation should work with clojure.set
functions.you can use supers
to see the interfaces that a class implements, it shouldn't be too hard to sort out the ones in this set that you'd need:
user=> (supers (class #{}))
#{clojure.lang.IEditableCollection java.lang.Runnable java.lang.Iterable clojure.lang.IFn java.util.concurrent.Callable clojure.lang.IPersistentSet clojure.lang.IPersistentCollection java.io.Serializable java.util.Collection clojure.lang.Counted clojure.lang.IMeta clojure.lang.AFn clojure.lang.IHashEq clojure.lang.Seqable clojure.lang.APersistentSet java.util.Set clojure.lang.IObj java.lang.Object}
I would guess java.util.Set and clojure.lang.IPersistentSet are the main ones to focus onusing more set operations to narrow it down 😄
user=> (-> (supers (class '#{})) (set/difference (supers (class []))))
#{clojure.lang.IPersistentSet clojure.lang.APersistentSet java.util.Set}
Really surprised no one mentioned SICP https://sarabander.github.io/sicp/html/1_002e3.xhtml#g_t1_002e3_002e2 > Using `let` to create local variables
If it helps @mll here's an example in next.jdbc
where I create an object that is compatible with Clojure's hash map: https://github.com/seancorfield/next-jdbc/blob/develop/src/next/jdbc/result_set.clj#L464
Thank you!
I am trying to use Buddy.works as a CI tool (CircleCI would not load my repo into a project). I am running into an issue where their Ubuntu image won't load my datomic library dependencies from AWS s3. I have updated the java certs, added my credentials into .aws in the image. I keep getting a classpath failure to load from the datomic maven repo. Any ideas?
may be better asking in #datomic, but what's the error?
rror building classpath. Could not find artifact com.datomic:dev-local:jar:0.9.232 in central (https://repo1.maven.org/maven2/)
The clojure
command is running as the root user, if that makes a difference.
does it work with your creds outside the image?
It works fine on my local MacOS 11.4 machine.
what are you using to download the deps?
I am not sure what you are asking. Here's my tools.deps
file:
{:paths ["src/main" "resources"]
:deps {org.clojure/clojure {:mvn/version "1.10.3"}
org.clojure/clojurescript {:mvn/version "1.10.866"}
org.clojure/tools.deps.alpha {:mvn/version "0.11.922"}
org.clojure/tools.namespace {:mvn/version "1.1.0"}
com.fulcrologic/fulcro {:mvn/version "3.4.22"
:exclusions [com.taoensso/sente]}
com.fulcrologic/fulcro-native {:mvn/version "0.0.8"}
com.fulcrologic/fulcro-garden-css {:mvn/version "3.0.7"}
com.fulcrologic/fulcro-rad {:mvn/version "1.0.9"}
com.fulcrologic/fulcro-websockets {:mvn/version "3.3.0"}
com.fulcrologic/guardrails {:mvn/version "1.1.4"}
garden/garden {:mvn/version "1.3.9"}
com.fulcrologic/semantic-ui-wrapper {:mvn/version "1.0.0"}
edn-query-language/eql {:mvn/version "0.0.8"}
org.clojure/core.async {:mvn/version "1.3.610"}
com.wsscode/pathom {:mvn/version "2.3.1"}
;; utility libraries
com.cognitect/transit-clj {:mvn/version "1.0.324"}
com.cognitect/transit-cljs {:mvn/version "0.8.264"}
tick/tick {:mvn/version "0.4.30-alpha"}
clojure-interop/cljs-web-api {:mvn/version "1.0.10"}
com.brunobonacci/safely {:mvn/version "0.7.0-alpha3"}
buddy/buddy-core {:mvn/version "1.10.1"}
;; stripe
com.stripe/stripe-java {:mvn/version "20.47.1"}
com.google.code.gson/gson {:mvn/version "2.8.6"}
;; web server
http-kit/http-kit {:mvn/version "2.5.3"}
bk/ring-gzip {:mvn/version "0.3.0"}
bidi/bidi {:mvn/version "2.1.6"}
hiccup/hiccup {:mvn/version "1.0.5"}
mount/mount {:mvn/version "0.1.16"}
ring/ring {:mvn/version "1.9.3"}
ring/ring-defaults {:mvn/version "0.3.2"}
cheshire/cheshire {:mvn/version "5.10.0"}
metosin/reitit {:mvn/version "0.5.13"}
;; logging
com.taoensso/timbre {:mvn/version "4.10.0"}
;; websockets
org.clojars.currentoor/sente {:mvn/version "1.14.1-SNAPSHOT"}
}
:mvn/repos {"datomic-cloud" {:url "<s3://datomic-releases-1fc2183a/maven/releases>"}}
:aliases {:cljs {:jvm-opts ["-DSENTE_ELIDE_JS_REQUIRE=true"]
:extra-deps {com.cognitect/transit-cljs {:mvn/version "0.8.256"}
com.fulcrologic/semantic-ui-wrapper {:mvn/version "1.0.0"}
binaryage/devtools {:mvn/version "1.0.3"}
binaryage/oops {:mvn/version "0.7.0"}}}
:dev {:extra-paths ["src/dev"]
:jvm-opts ["-Dtrace" "-Dguardrails.enabled=true"]
:extra-deps {org.clojure/tools.namespace {:mvn/version "0.3.1"}
thheller/shadow-cljs {:mvn/version "2.14.2"}
com.datomic/ion-dev {:mvn/version "0.9.282"}
com.datomic/dev-local {:mvn/version "0.9.232"}
com.google.guava/guava {:mvn/version "30.1-jre"}}}
:datomic-cloud {:extra-deps {com.datomic/ion {:mvn/version "0.9.50"}
com.fulcrologic/fulcro-rad-datomic {:mvn/version "1.0.7"}
com.datomic/client-cloud {:mvn/version "0.8.105"}}}
:clj-test {:extra-paths ["test"]
:extra-deps {lambdaisland/kaocha {:mvn/version "1.0.861"}
lambdaisland/kaocha-cucumber {:mvn/version "0.0-53"}
org.clojure/test.check {:mvn/version "1.1.0"}
fulcrologic/fulcro-spec {:mvn/version "3.1.12"}}}
}}
The :mvn/repos
is what I am using, I don't explicitly download the jars. Should I?
I was asking if you're using Clojure CLI or lein or something else
Clojure CLI
one tool that is available is the -P flag to prepare your environment (will download jars, build the classpath, etc) which can be useful in CI scenario
the most common reason you can't access the datomic s3 repo is that your creds don't support s3 ops
but that seems not to be the case if they work elsewhere
you could try narrowing this by using the aws cli to download directly from the repo
Ok, I'll try that, thanks @alexmiller
I think in the current iteration of dev-tools with maven support, you're actually using a different maven repo: https://dev-tools.cognitect.com/maven/releases/ which you don't have
when you download dev-tools, it has all that setup info included
the :mvn/repos should include "cognitect-dev-tools" {:url "<https://dev-tools.cognitect.com/maven/releases/>"}
and then your ~/.m2/settings.xml should have:
<server>
<id>cognitect-dev-tools</id>
<username>YOUR-EMAIL</username>
<password>YOUR-PW</password>
</server>
Ok.
you said this was running as root - be sure you are getting the right ~ for root (this is something I've gotten wrong a few times)