Fork me on GitHub
#clojure
<
2021-06-07
>
mll05:06:10

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?

seancorfield05:06:47

@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.

mll05:06:33

Ok, so you suggest @seancorfield that I should focus on implementing java interfaces and not use the "defprotocol" for this one at all?

seancorfield05:06:44

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.

seancorfield05:06:58

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

mll05:06:18

Thank you!

noisesmith15:06:19

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 on

noisesmith15:06:38

using more set operations to narrow it down 😄

user=> (-> (supers (class '#{})) (set/difference (supers (class []))))
#{clojure.lang.IPersistentSet clojure.lang.APersistentSet java.util.Set}

hadils16:06:44

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?

alexmiller16:06:32

may be better asking in #datomic, but what's the error?

hadils16:06:03

rror building classpath. Could not find artifact com.datomic:dev-local:jar:0.9.232 in central (https://repo1.maven.org/maven2/)

hadils16:06:06

The clojure command is running as the root user, if that makes a difference.

alexmiller16:06:33

does it work with your creds outside the image?

hadils16:06:14

It works fine on my local MacOS 11.4 machine.

alexmiller16:06:53

what are you using to download the deps?

hadils16:06:24

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 ""}}

 :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"}}}
             }}

hadils16:06:10

The :mvn/repos is what I am using, I don't explicitly download the jars. Should I?

alexmiller16:06:14

I was asking if you're using Clojure CLI or lein or something else

hadils16:06:38

Clojure CLI

alexmiller16:06:51

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

alexmiller16:06:14

the most common reason you can't access the datomic s3 repo is that your creds don't support s3 ops

alexmiller16:06:48

but that seems not to be the case if they work elsewhere

alexmiller16:06:40

you could try narrowing this by using the aws cli to download directly from the repo

hadils16:06:08

Ok, I'll try that, thanks @alexmiller

alexmiller17:06:23

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

alexmiller17:06:33

when you download dev-tools, it has all that setup info included

alexmiller17:06:01

the :mvn/repos should include "cognitect-dev-tools" {:url ""}

alexmiller17:06:44

and then your ~/.m2/settings.xml should have:

<server>
       <id>cognitect-dev-tools</id>
       <username>YOUR-EMAIL</username>
       <password>YOUR-PW</password>
    </server>

noisesmith20:06:31

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)