Fork me on GitHub
#clojure
<
2020-02-19
>
alfredx00:02:29

Would anyone have example, or link to examples where we can enable/setup/retrieve some stats/metrics from aleph server (started using aleph.http/start-server) for things like, error count/error rate in the last 5 mins?

pithyless06:02:02

You can subscribe to connection-pool stats via register-connection-stats-callback and there is also a rejected-handler you can override in start-server. https://aleph.io/codox/aleph/aleph.http.html#var-register-connection-stats-callback https://aleph.io/codox/aleph/aleph.http.html#var-start-server

pithyless06:02:12

If you're handling the request via manifold.executor, there is also register-execute-pool-stats-callback and register-wait-pool-stats-callback

alfredx11:02:12

I am not using executor in our app. Did an experiment the register-connection-stats-callback callback appears to be stats for when using aleph as http client. Not stats for server started using start-server.

alfredx11:02:10

Its doc says Registers a callback which will be called with connection-pool stats.. Where I think connection-pool is not for a http-server.

pithyless11:02:27

@UM8SD6W8G good point about the http client stats-callback; if you're not passing in an explicit executor, aleph is creating an utilization-executor [0]. You probably need to pass in an instance of instrumented-executor [1] to your start-server. This should give you the ability to monitor the stats. [0] https://github.com/ztellman/aleph/blob/5cc7bcab723bf3b64de7998fc782531c554636e5/src/aleph/http/server.clj#L532-L536 [1] https://github.com/ztellman/manifold/blob/master/src/manifold/executor.clj#L83-L95

Mark W00:02:06

Trying to get started using origami (http://origamidocs.hellonico.info/#/?id=origami-computer-vision-made-simple) , created a new lein app, then ran lein deps and it retrieved all packages....however, when then running lein repl it couldn't find opencv-native

Mark W00:02:40

anybody having the same issue? I can't load the repl since the opencv-native package can't be found....any help is greatly appreciated, thanks!

Mark W01:02:03

nvm was a network issue

Eduardo Mata02:02:45

Has anyone ever use Taoensso's libary, Tufte? If yes, how could I format the stats map to comeback as a string saying 12.00ms instead a long integer?

gerred02:02:59

@contact904 can you provide more context on what you're seeing? the standard out looks like the percentiles should be in ms

Eduardo Mata03:02:57

Was this good context?

fabrao03:02:23

hello, how to I use this *TransferLearningHelper*(*ComputationGraph* orig, java.lang.String... frozenOutputAt) in clojure?

fabrao03:02:47

java.lang.String... value ?

fabrao03:02:14

I tried with single string, but no success

fabrao03:02:34

got it java.lang.String... value -> (into-array ["some"])

hindol04:02:15

That's one of the gotchas of Java interop. For vararg you need to pass an actual Java array.

ujjwalt07:02:54

I come from a Rails background. What is the quickest or default way to do web development in Clojure especially with Datomic.

p-himik08:02:03

This is a nice overview article: https://purelyfunctional.tv/mini-guide/what-web-framework-should-i-use-in-clojure/ There's also this: https://luminusweb.com/ But I agree with didibus and with the article in that it's better to start with small independent components and build your system up from that. Personally, I like using https://github.com/juxt/edge as a starting point and a "glue".

pithyless09:02:41

It's neither quick* nor the default** way; but I feel https://fulcro.fulcrologic.com/ is a nice one-stop-shop for building SPAs in Clojure. (And the Pathom integration is a well-paved path to using Datomic). *I wouldn't call it quick, because there is a lot of things to learn. **There is no default. :)

👍 8
vemv13:02:22

The Datomic requirement is the most hard to reconcile coming from a Rails background (I'm also a Rails-er) For me it was somewhat hard to completelly ditch Rails' ActiveRecord because it's a really nice ORM. I think the last two nails in the coffin were: https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/EffectivePrograms.md https://github.com/jkk/honeysql

souenzzo17:02:00

+1 for #fulcro and #pathom 🙂

didibus08:02:03

@ujjwalt Clojure doesn't have a canonical web development framework the way that Ruby has Rails, and Python has Django. The best way to learn (and get started) is for you to try and build a minimal website using Ring: https://github.com/ring-clojure/ring , Ring defaults: https://github.com/ring-clojure/ring-defaults , Compojure: https://github.com/weavejester/compojure and Hiccup: https://github.com/weavejester/hiccup with Datomic as your DB

👍 4
didibus08:02:58

If you run lein new compojure you'll get a minimal project setup with ring, ring-defaults and compojure. You'll need to add hiccup manually after that to it.

👍 4
borkdude13:02:04

I got an issue in clj-kondo which uses transit-clj with a warning that transit-clj depends on a package with a security issue: https://github.com/borkdude/clj-kondo/issues/762

Alex Miller (Clojure team)13:02:04

They should report it on transit-clj

Alex Miller (Clojure team)14:02:46

bumping message pack versions is potentially a non-trivial update so not something to do without some review

littleli14:02:15

@alexmiller do they have a lot of breaking changes?

Alex Miller (Clojure team)14:02:03

not to my memory, but there are sometimes changes that affect transit, particularly when making big updates

borkdude14:02:58

false alarm

borkdude14:02:08

it was only affecting C#

Alex Miller (Clojure team)14:02:21

sometimes also raises questions about updating msgpack on the other transit libs too

Alex Miller (Clojure team)14:02:43

still worthy of periodic review :)

Alex Miller (Clojure team)14:02:12

avoiding dependency checker false positives has some value too

Alex Miller (Clojure team)14:02:26

most people don't look too closely at the CVEs

grounded_sage15:02:05

How do I get the data from a tagged literal? eg: #time/offset-date-time "2020-04-04T18:30+02:00"

Alex Miller (Clojure team)15:02:42

depends whether you have a data reader defined for that tag or not

Alex Miller (Clojure team)15:02:13

if so, then that data reader will be automatically called, which creates an object, and how you get data out of it depends entirely on what that object/data is

Alex Miller (Clojure team)15:02:07

if not, then there are ways to use a generic reader like tagged-literal to just read it as tag+form

Alex Miller (Clojure team)15:02:16

but that is not installed by default

grounded_sage15:02:00

I’m using the Tick library for extra context. I think all I need is to read it though as I am putting it into JSON for later consumption.

Audrius15:02:40

Hello, I can see some readers defined in *data-readers* How do I define more readers and writers? In particular I am trying to send JS objects thru wire

borkdude15:02:54

I'm considering to change the reader conditional logic for babashka. The reason is that many .cljc libs already work without changing the code, but babashka currently only chooses the :bb branch in a reader conditional. This means that a lib like lambdaisland/regal has to be forked and all :clj branches have to be copied to a :bb branch: https://github.com/borkdude/regal/commit/42906e57bf45e9d6cb699700ea19e653757f535d What I'm proposing is that babashka takes the first :bb or :clj branch (whichever comes first). Anything I should be aware of why this may be bad design?

Alex Miller (Clojure team)15:02:42

ideally reader conditionals should be making greater leverage of the :default branch such that this wouldn't be needed

borkdude15:02:52

most often libs have specific :clj or :cljs branches concerning interop differences. a :default interop branch probably doesn't work an "all remaining platforms"

Alex Miller (Clojure team)15:02:06

yeah, it depends a lot on the details

Alex Miller (Clojure team)15:02:18

what's right for bb is hard to say

borkdude15:02:32

bb aims to be compatible with JVM clojure

Alex Miller (Clojure team)15:02:39

I mean in bb you control the reader, so you could make it pretend to be :clj platform

Alex Miller (Clojure team)15:02:50

or inject both :clj and :bb features

borkdude15:02:29

by allowing both, users can always override :clj by putting :bb first. where it might not be so nice is in requires: (:require #?(:bb nil :clj foo :cljs bar)) (this is incorrect syntax) but you can always (:require #[email protected](:bb [] :clj [foo] :cljs [bar]) as a workaround.

Alex Miller (Clojure team)15:02:31

I'd kind of recommend a qualified keyword for your platform feature too (I don't think that's doc'ed anywhere, but seems like it would follow other such advice)

borkdude15:02:15

I've just followed what other platforms already were doing: :clj, :cljs, :cljr, :clje (Erlang), :joker

Audrius15:02:45

What is joker platform 😮

Alex Miller (Clojure team)15:02:06

Clojure interpreter written in Go

Alex Miller (Clojure team)15:02:08

to be clear, only those first three are "official" :)

Alex Miller (Clojure team)15:02:16

just b/c others did it, doesn't make it right :)

borkdude15:02:36

I go by the official examples 😉

Alex Miller (Clojure team)15:02:27

I added a note to that page :)

Alex Miller (Clojure team)15:02:47

"Implementors of non-official Clojure platforms should use a qualified keyword for their platform feature."

borkdude15:02:25

do you have any suggestions what kind of namespace those platforms should use? clojerl/foo joker/foo?

borkdude15:02:34

and what should be the second part?

borkdude15:02:46

I mean, bb/bb? this doesn't help anyone I guess

dpsutton15:02:37

:platform/bb?

grounded_sage15:02:55

I ended up just calling (str …) on it. Achieves the same result. 😅

borkdude15:02:28

how does platform/foo help anyone? I don't see the point. if everyone uses platform you still could get clashes?

borkdude15:02:23

unless someone can convince me of the need to change the current feature name and has a concrete suggestion, I'll probably leave it for now

vlaaad15:02:28

:borkdude/bb?

vlaaad15:02:17

it helps to identify what bb means. There might be many bbs, but there is only one borkdude 🙂

borkdude15:02:42

too verbose

borkdude15:02:51

and what if bb moves to its own org later on

borkdude15:02:17

I've also thrown this into the #joker to see what they have to say

borkdude15:02:06

I'm willing to add another feature name to the babashka reader if there is somewhat more clear guidance on what to name these things, but :bb has been in use for a while and I'm going to keep supporting that because of not breaking things

jeroenvandijk15:02:05

what about :`bb/clj` the platform is bb and it's compatible with clj. Who knows there will be a version that supports cljs

jeroenvandijk15:02:39

For Sci this is more clear, there is a :cljs and :clj mode (or I think there will have to be one in the future)

borkdude15:02:42

now we're talking

borkdude15:02:20

sci is configurable: you can say what features you want to read in the eval-string options

jeroenvandijk15:02:35

ah yeah that's true, never mind than 🙂

borkdude15:02:13

I like :bb/clj

jeroenvandijk15:02:48

oh wait I do have an example with Sci in mind 🙂 I have code that I want to run on the server and on the client, but they would be different in implementation so it would :sci/clj and :sci/cljs, but yeah I could control the reader myself indeed 🙂

Alex Miller (Clojure team)15:02:20

the purpose of using a qualifier is to avoid collisions, and the only way to do that is with a qualifier you "control" either via dns, or trademark, or maybe some conferred identity like github

Alex Miller (Clojure team)15:02:45

so "platform" provides no value

jeroenvandijk15:02:11

Ok makes sense. Would you consider bb a trademark in this case?

borkdude15:02:34

@alexmiller if the goal is to avoid collisions, you don't need namespaced keywords. you can just use :nl.michielborkent.babashka as the keyword

Alex Miller (Clojure team)15:02:38

no, as I presume it has not been trademarked

Alex Miller (Clojure team)15:02:52

.'s should only be used in the qualifier part of a keyword

Alex Miller (Clojure team)15:02:35

per https://clojure.org/reference/reader on keywords, "They cannot contain '.' in the name part, or name classes"

jeroenvandijk15:02:14

babashka is trademarked via Dutch copyright (auteursrecht) i think (but I'm not a laywer)

borkdude15:02:55

part of me wished I never asked something today

😁 8
dabrazhe16:02:10

Hi. Is someone using AWS lambda with a handler that :implements [com.amazonaws.services.lambda.runtime.RequestHandler] ? I'd like to know how to destructure the context argument as in (defn -handleRequest [this event context] It has type of lambdainternal.api.LambdaContext In Python it's smth like context.log_stream_name

borkdude16:02:07

ok, since the goal is to avoid collisions, I'm happy to talk with anyone who thinks he/she has more rights to the :bb tag and I'll make changes if necessary to avoid a lawsuit.

vlaaad18:02:51

There are 52k repos on the GitHub if you search for bb :)

borkdude18:02:26

and how many using it as a feature keyword reader conditionals?

borkdude16:02:48

Alex: might be nice to add "to avoid collissions" to the sentence here to give a reason why it's good practice to do this: > Implementors of non-official Clojure platforms should use a qualified keyword for their platform feature.

Ramon Rios16:02:48

Hey everyone. I have a vector with email addresses in strings ["[email protected]"] . I have a function that matches a email with a regex , but now i have to check each address in this vector. i tought of use doseq but it always returns me a nil. Can you folks have an idea?

(defn- match-regex?
  "Check if the string matches the regex"
  [v regex]
  (boolean (re-matches regex v)))

(defn is-email-address?
  "Check if input is a valid email address"
  [input]
  (if (nil? input)
    false
    (doseq [inputs input] )
    (match-regex? input email-address-regex)))
My current code. it gets one string and matches with the regex for email

hindol18:02:42

Anything that starts with do... is primarily used for the side-effects. The return value becomes less important and they are often nil.

Ramon Rios18:02:05

Thank you for this tip.

hindol18:02:23

Except for do, where the last thing is returned. Many forms have an implicit do in them such as when, let, fn. That is how they support multiple expressions in them and the last one is returned.

hindol18:02:08

Otherwise, for etc. don't even support multiple expressions in them. if supports exactly two but you can omit the second.

Ramon Rios19:02:29

Thank you Hindol

👍 4
dpsutton16:02:24

(every? #(re-matches email-regex %) coll-of-emails)

Ramon Rios17:02:58

Thank you !!

Jakob Durstberger19:02:55

Hello folks 🙂 I am currently having some trouble with protocols and I think I have misunderstood them a bit. I have a piece of code that talks to an AWS queue that I would like to test, so I want to create an abstraction over the queue so I can provide a stub for testing. My code needs to call (sqs/find-queue credentials queue-name) which returns a url. I can then send a message to that queue with (sqs/send-message credentials queue message). I thought it would be a good idea to create a protocol and implement it with a deftype but I am unsure if a) this is the right approach and b) if it is where sqs/find-queue ... should go.

(defprotocol Queue
  (send-message [message]))

(deftype SQSQueue [credentials queue-name]
  ;; somehow call find-queue
  (send-message [message]
    (sqs/send-message credentials queue message)) ;;not sure how I can get queue in there?
Any help is appreciated :)

chrisulloa19:02:28

You could certainly call find-queue in send-message

(send-message [message]
  (let [queue (sqs/find-queue credentials queue-name)]
    (sqs/send-message credentials queue message)))

chrisulloa19:02:03

since you are storing the queue-name and not the actual queue you’ll need to retrieve it before sending the message

chrisulloa19:02:56

I think your deftype should implement the protocol as well

(deftype SQSQueue [credentials queue-name]
  Queue
  (send-message ...))

hiredman19:02:27

your send-message implementation is not correct

hiredman19:02:38

protocol definition is wrong to

hiredman19:02:03

a protocol function takes the object it is dispatching on as the first argument

chrisulloa19:02:47

ahh yeah, i call that first arg this to not forget

Jakob Durstberger19:02:32

@hiredman Sorry, yes you are right I just wrote it directly in slack. @christian.gonzalez I don't want to call find-queue every time as it is an extra network call. I think it would be nicer to only find the queue once and then keep the reference somewhere.

chrisulloa19:02:06

i would instead store the queue instead of (or in addition to) the queue-name when creating your SQSQueue

hiredman19:02:20

I would suggest you stop writing deftypes and protocols

hiredman19:02:17

I think the trappings of these other things are obscuring it, if you just write some functions the answer the pretty apparent

chrisulloa19:02:55

yeah, probably not the best starting approach unless it’s an exercise in learning protocols

Jakob Durstberger19:02:47

I am definitely not stuck on the approach. I come from an OO background so my brain goes "I need an interface". Happy to do something that is more idiomatic in clojure, unfortunately I don't know what that would look like

hiredman19:02:59

the interface is fine, I am not saying there is anything wrong with it, I am saying take a step back from it, ask yourself how you would solve your problem with out any of that stuff, and the answer with all of that stuff is the same

hiredman19:02:40

so like, if you didn't have a deftype for SQSQueue, you might represent it as a hash map

hiredman19:02:09

and you might write a function that takes credentials and queue-name and returns your hash map

hiredman19:02:19

and send-message would just be a function that takes that hash map and a message

hiredman19:02:01

given that setup, it is fairly obvious the place to put the call to find-queue is in that first function

Chris Lester19:02:12

If you've no examples of clojure code to work from, run through one of the clojure books like Joy of clojure or clojure for the brave and true. Can also take a look at some github repos like CircleCI or Metosin, but those get fairly complex if you have no experience writing Clojure.

hiredman19:02:30

replace the hash-map with your deftype and the send-message function with the protocol function, done

hiredman19:02:46

(or just leave out the protocol bits anyway)

chrisulloa19:02:30

it would make more sense if you had different types of queues you need to juggle in your code, like a rabbit queue and an sqs queue then maybe the polymorphism would clean up your code, but usually easier to start without using interfaces and move to them if you really need to

hindol20:02:29

@jakob.durstberger I suggest you read this first. It was quite the eye opener for me. http://mishadoff.com/blog/clojure-design-patterns/

Jakob Durstberger20:02:16

Thanks, that looks really interesting

hindol20:02:44

If you read the official docs on http://clojure.org, defprotocol and family exist to take advantage of the very optimized type based dispatch from the JVM. The community generally discourages liberal use of types.

hindol20:02:38

I am from an OOP background too, and even I too quickly associated defprotocol with interfaces.

👍 4
Jakob Durstberger20:02:39

Thank you that is all already helpful. > it would make more sense if you had different types of queues you need to juggle in your code, like a rabbit queue and an sqs queue I think I would have 2, one for testing and one SQS queue. So that's where I kinda started to think that using a protocol might be a good idea.

chrisulloa20:02:33

there are ways to mock functions like send-message without using protocols

Jakob Durstberger20:02:55

Like using with-redef?

Jakob Durstberger20:02:20

just redef find-queue and send-message? I guess that would make it easier 😄

chrisulloa20:02:28

yup that would work

Jakob Durstberger20:02:34

Thank you all. That was really helpful

jeroenvandijk08:02:59

@jakob.durstberger Although I agree that protocols are not easiest to start with, your idea is good! And I don't agree with what people are saying here about with-redef . Having protocol abstractions is super useful, even if you only have one type of queue (doing it this way all the time). You probably do want to use defrecord over deftype for the implementation. deftype is more optimized, but less user friendly

Jakob Durstberger09:02:06

I just got around to replace amazonica with cognitects aws sdk so I haven't had time to play around with the protocol a bit more. Thanks for telling me about defrecord

Chris Lester20:02:39

I've a spec question. I can't seem to get the function specs to exercise (or run with s/check) but I can get the spec def's to generate. When I run the fn spec I get back: storage-proxy.core=> (s/exercise-fn `q/read-lf-programs-by-ref!) Execution error at v2-storage-proxy.core/eval7802 (form-init12043777169450783562.clj:1). No :args spec found, can't generate ... am I doing something wrong in the fdef definition?

Alex Miller (Clojure team)20:02:50

(s/get-spec `read-programs!) will return the fspec for read-programs!

Alex Miller (Clojure team)20:02:21

that spec supports keyword lookup with :args, :ret

Alex Miller (Clojure team)20:02:12

do you a) see the function spec, b) see the args spec in that function spec, c) can you exercise the args spec, and d) up to 100s of samples

Chris Lester20:02:36

I see nil 🙂

Chris Lester20:02:50

...which is confusing lol.

Alex Miller (Clojure team)20:02:00

well, then the spec is not in the registry

Alex Miller (Clojure team)20:02:23

you may need to backtick the function name to fully qualify?

Chris Lester20:02:35

Definitely isn't if that's returning nil, which makes the problem easier to understand. Not sure how that is but that's likely it.

Alex Miller (Clojure team)20:02:40

I don't have enough context here to really tell precisely

Chris Lester20:02:20

I am backticking - (s/get-spec `q/read-lf-programs-by-ref!) ... for example is returning nil. The def is in the snippet above.

Chris Lester20:02:34

q being an alias to the namespace.

Alex Miller (Clojure team)20:02:50

that doesn't match your fdef for read-programs!, not sure if this is same example

Alex Miller (Clojure team)20:02:26

trying to say read-lf-programs-by-ref! != read-programs! so I'm a little confused

Chris Lester20:02:39

Sorry, same codebase ...(s/get-spec `q/read-lf-programs!) is also nil.

Chris Lester20:02:19

It's a generalized problem for all s/fdefs right now.

Alex Miller (Clojure team)20:02:59

if you (-> s/get-registry keys sort) do you see stuff in your registry?

Alex Miller (Clojure team)20:02:27

the registry is just a map, with qualified symbol keys for fdefs, not much magic here

Chris Lester20:02:38

No, get "no such var".

Chris Lester20:02:59

v2-storage-proxy.core=> (require `[clojure.spec.alpha :as s]) nil v2-storage-proxy.core=> v2-storage-proxy.core=> (-> s/get-registry keys sort) Syntax error compiling at (/private/var/folders/z2/q807rqzd2k5gr1hpywg3p49xw_x00z/T/form-init12043777169450783562.clj:1:1). No such var: s/get-registry

Alex Miller (Clojure team)20:02:21

Sorry, should be parens around that :)

Alex Miller (Clojure team)20:02:42

I let my dog type that part, not my fault

ghadi21:02:17

underrated

Chris Lester20:02:15

s/registry exists ... dumping that.

Chris Lester20:02:29

I do see them in the registy

Chris Lester20:02:54

For some reason, after calling (s/registry) to get the map ... now the lein repl (but not Calva's) attempts to exercise the function spec.

pez22:02:23

Not quite following, but if you think Calva should behave differently here, please file an issue. ❤️

Chris Lester20:02:48

...well, does exercise it. So that's working, by magic, from the lein repl now. lol.

Alex Miller (Clojure team)20:02:32

I’m thinking maybe your problem is not spec :)

💯 4
andrea.crotti21:02:40

is there a smart way to handle working on multiple projects at the same time, which sometimes can conflict on fighweel/shadow-cljs/ring ports?

andrea.crotti21:02:12

I can try to have different ports in every projects but it's not always easy and a bit of a pain anyway

vemv21:02:31

wdyt of (or (System/getProperty "my-proj.the-port") 8080)? jvm properties can be merged/activated at will which is cleaner than System/getenv (which would also work)

andrea.crotti21:02:36

ah cool, tbf almost all the projects use aero

andrea.crotti21:02:51

and in most of them I can override things in a user.edn file

👀 4
andrea.crotti21:02:08

I was thinking though about something more magical at a lower level, that just tries another port if the port it wants it's busy

vemv22:02:54

Yeah I've wanted something like that sometimes. OTOH, sometimes multiple things need to be aware of the chosen port (e.g. server + asset pipeline), things could get unwieldy there

dominicm22:02:13

Also, it's annoying to remember as a user :) My thoughts when designing this for edge were: - cache the choice - use a special reader macro that chooses nice ports I ended up just generating nice ports randomly on project creation.

sogaiu23:02:51

for socket repls of jvms i have something that can externally start a socket repl on your port of choice (or choose something available) -- after the jvm has started: https://github.com/sogaiu/alc.start-repl i use the following to attempt detection of socket repl ports (and other types) at runtime: https://github.com/sogaiu/alc.enum-repls -- i use this from tooling to guess ports so i don't have to look them up manually

sogaiu23:02:22

these are both typically invoked not at the repl but at the command line or via external process invocation

cfleming23:02:17

Many of my users are reporting a problem in the latest version of Cursive, and I cannot figure it out. The error looks like this:

Error running REPL: Receiver class cursive.repl.toolwindow$repl_listener$reify__11845 does not define or inherit an implementation of the resolved method 'abstract void contentAdded(com.intellij.ui.content.ContentManagerEvent)' of interface com.intellij.ui.content.ContentManagerListener.

cfleming23:02:24

The reified object looks like this:

(reify
  ContentManagerListener
  (contentRemoveQuery [this event]
    ...)
  ProjectManagerListener
  (projectOpened [this project])
  (canCloseProject [this closing-project]
    ...)
  (projectClosed [this project])
  (projectClosing [this project]
    ...)
  (projectClosingBeforeSave [this project]))
and the interface looks like this:
public interface ContentManagerListener extends EventListener {
  default void contentAdded(@NotNull ContentManagerEvent event) {
  }

  default void contentRemoved(@NotNull ContentManagerEvent event) {
  }

  default void contentRemoveQuery(@NotNull ContentManagerEvent event) {
  }

  default void selectionChanged(@NotNull ContentManagerEvent event) {
  }
}

cfleming23:02:45

(the reified object is redacted for brevity)

cfleming23:02:32

Since all the interface methods have default implementations, as far as I know this should be fine, and it always works for me locally - I’ve debugged through it etc.

cfleming23:02:07

Since this only happens in released builds and never locally, hopefully I can rule out AOT crud, because I do a clean build when releasing.

cfleming23:02:40

Are there any edge cases to using reify like this that I should be aware of? For the life of me I can’t see how this error could happen.

hiredman23:02:51

I haven't had to deal with default methods much so I can't say for sure, but from my understanding I would expect that to work. It does look like the defaults were added in 2018, could your users be running an old version or something?

cfleming23:02:37

No, they’re either running the 2019.3 (late last year) or 2020.1 (in beta now) versions.

cfleming23:02:55

Oh, wait…. they’re actually not in 2019.3. I wonder if it’s actually only a problem in 2019.3 and users have reported the version incorrectly - that is the only thing I can think of that would make sense. Thanks, I’ll test that out.