beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
2021-05-11T00:30:17.495900Z

@factorhengineering clojure(script) has to work with the platform tools. So your html's script tag has to point to the js file location, shadow-cljs is a build tool helped to provide some helper functions in organizing that. Basically every dev is going to want to do the same thing and with a library like shadow we can all be on the same page: reusable functionality, shared mindspace, optimizations, etc... So i would say its definitely a shadow cljs question. But the shadow docs are really good. Don't hesitate to ask me questions though šŸ™‚

FHE 2021-05-11T01:32:00.496100Z

I think I ended up starting in the deep end of the pool with: https://shadow-cljs.github.io/docs/UsersGuide.html While I was away from my computer and had a few minutes with my phone i found this: https://github.com/shadow-cljs/quickstart-browser ...kind of wish I had stumbled in that first. Ha. Going to go through that now.

FHE 2021-05-11T01:47:48.496500Z

@drewverlee Can you shed any light on the 20MB (and 200ish folders and 1000ish files) installed in a fresh project folder by npx create-cljs-project my-project (as specified in the User Guide at the 1st link above)? ...whereas git cloning the quickstart folder+file set (as specified in the Quickstart at the 2nd link above) yields 5 folders and 7 files? Is the first, heavy installation just trying to guess at many, many libraries that a person might want?

FHE 2021-05-11T01:52:24.496800Z

Oh...finishing the installation for the quick guide project actually results in another massive thing, slightly larger than the user guide one even. I guess my question about what the point of all those file is still stands, though.

2021-05-11T01:55:15.497Z

Npx is a way to localize Js, it puts it all on your directory, rather then globally. This is better for the obvious reasons. That's likely what your seeing.

2021-05-11T01:55:38.497200Z

Well, I shouldn't say obvious, but I'm on my phone.

FHE 2021-05-11T01:56:54.497400Z

OK. Maybe it will make more sense to me soon. šŸ˜‰

2021-05-11T01:58:39.497600Z

The files on your computer are used to build the files that will be sent to the browser, you don't have to be to concerned about the formers size.

2021-05-11T01:59:10.497800Z

There are many steps to reduce size between the two.

2021-05-11T02:01:55.498Z

This isn't clojure ecosystem thing, it's more of a sensible way to handle deps. It's main stream, nearly every language does some version of it. Then again in assuming that's the issue, without seeing them files on question I might be leading you astray.

FHE 2021-05-11T02:23:17.498200Z

Well in the first case, I'm not sure if the create-cljs-projectpart of the npx command is linked to shadow-cljs, but it seems like it's a pretty generic thing, so I did guess maybe everyone's JS or at least CLJS project folders start huge like that.

seancorfield 2021-05-11T02:26:33.498400Z

@factorhengineering Are you talking about the node_modules folder?

seancorfield 2021-05-11T02:30:08.498600Z

Yeah, you are, I just tried that command. Think of node_modules as the ā€œMaven repositoryā€ of the JS world ā€” go look in ~/.m2/repository for what Maven (and Leiningen/Clojure CLI) has installed on your system! šŸ™‚

seancorfield 2021-05-11T02:31:45.498800Z

That folders contains over 23,000 files for me in about 8,000 directories for me ā€” it positively dwarfs what npm/`npx` lays down in node_modules! šŸ˜†

FHE 2021-05-11T02:39:50.499100Z

@seancorfield Yes, the node_modules folder.

seancorfield 2021-05-11T02:40:56.499300Z

Just ignore it. Like I say, itā€™s the ā€œMaven repoā€ of the JS world.

FHE 2021-05-11T02:41:06.499500Z

I just took a peek in ~/.m2/repository folder. Yes..lots of stuff. Actually, I'm happy to see cider and hiccupthere. Both are things I thought I might want but would need separate installations later.

seancorfield 2021-05-11T02:42:15.499700Z

Itā€™s all just libraries ā€” in both the JS world and the Java world. You donā€™t really ā€œinstallā€ stuff in the Java world: the tools you use to run your code (or build your artifacts) automatically download the dependencies they need.

seancorfield 2021-05-11T02:42:38.499900Z

package.json is the deps.edn of the JS world.

FHE 2021-05-11T02:46:50Z

You anticipated a question I was about to ask. Thanks. šŸ˜‰

FHE 2021-05-11T02:47:40.000200Z

...and I guess if I'm using shadow-cljs, I'm going to be manipulating (maybe not manually but still...) shadow-cljs.edn instead of deps.edn?

seancorfield 2021-05-11T02:49:16.000400Z

Well, shadow-cljs.edn is all about the front end stuff youā€™d be doing with Shadow-cljs. If you also build a backend piece for the app, youā€™ll need deps.edn (or project.clj) for the Clojure part.

seancorfield 2021-05-11T02:49:55.000600Z

Shadow-cljs is kind of its own ā€œislandā€. But itā€™s an island that is very friendly to npm stuff if thatā€™s what you need.

FHE 2021-05-11T02:53:11.000800Z

Aha. But can't back-end stuff also be done with shadow-cljs? I thought the genesis of Node.js was for back-end stuff, and shadow-cljs seems pretty linked with node.

2021-05-11T03:04:02.001Z

Shadow is for producing JS. There are a lot of full stack frameworks in clojure. Try luminous, or fulcro. Both have options to use shadow. Your time learning shadow will pay off, it's widely adopted.

FHE 2021-05-11T03:09:53.001500Z

So usable for server-side, but not without some other...what's the word...tooling?

FHE 2021-05-11T03:10:16.001700Z

(like Luminus or Fulcro)

FHE 2021-05-11T03:11:36.001900Z

I was going to try Luminus as my starting point, by the way (and did run into mention of Fulcro as well while trying to wrap my head around all this before actually setting anything up), but I was advised that might not be the best place to start.

FHE 2021-05-11T03:13:02.002100Z

Maybe soon, though! I thought I could use shadow-cljs (and nothing more) to make a desktop app, by the way. If that's not true, then I may need Luminus or something like it sooner than I thought.

indy 2021-05-11T07:25:45.009200Z

Hello. Was looking for information on when to use a case form and when to use multimethods (I want to dispatch on value), and also some performance comparisons. And I came across this https://insideclojure.org/2015/04/27/poly-perf/. When Alex says case is "closed", does that mean anything more than "one has to add another case condition"? In contrast, multimethods are "open" because, you have define a multimethod external to the defmulti? Not quite able to understand why case is more closed than multimethods. If I need to make some changes to the value I'm dispatching on, I have to change the mulimethod definition as well isn't it?

gon 2021-05-11T07:48:05.010800Z

if you are using a third party library where things are defined as case over defmulti in your code you are able to extend the defmulti, but not the case..

1
phronmophobic 2021-05-11T07:48:49.011Z

One major difference between case and defmulti is that defmulti is more flexible. There's a couple of ways the difference in flexibility manifests. For case, there's really only one way to add an additional clause which is to add another clause within the case statement. For defmulti , there are multiple options for extending a multi method. For programs that are fairly static, the code for using either defmulti or case might look largely the same. but for a dynamic program, defmulti 's flexibilty can really shine. Two types of extra flexibility come to mind. 1. Allowing library users to provide extensions. See https://clojuredocs.org/clojure.core/print-method for an example 2. Extending multi methods at run time. Typically, programs don't take advantage of this in production, but it's pretty useful in development if you're doing repl driven development. The idea is that you create a multi method that has 0 clauses and add/update clauses using your attached repl until everything works.

indy 2021-05-11T08:00:35.011200Z

Thanks, the library bit makes sense. Need to try out the REPL friendliness of multimethods. šŸ‘:skin-tone-4:

2021-05-11T09:08:20.015300Z

is there any name-spaced syntax for set similar like map, #{:a.b/foo :a.b/bar :a.b/baz} can i take this a.b out for once?

2021-05-11T09:32:28.015500Z

no, but even for maps you canā€™t take multiple values only by namespace

2021-05-11T09:46:31.015700Z

#:a.b {:foo 123 :bar 123} in map i can do this, and the key would all become :a.b/foo :a.b/bar, i guess there's no such thing for set then šŸ˜„

Endre Bakken Stovner 2021-05-11T10:06:01.018300Z

Does anyone have any idea what this error might be due to? I think it happens in a Luminus project where I am trying to set up Sente. The error happens when Sente tries to connect to the server. I would love some hints on how to debug it or tips if anyone knows what might be wrong.

java.lang.IllegalArgumentException: No implementation of method: :on-close of protocol: #'org.httpkit.server/Channel found for class: nil
	at clojure.core$_cache_protocol_fn.invokeStatic(core_deftype.clj:583)
	at clojure.core$_cache_protocol_fn.invoke(core_deftype.clj:575)
	at org.httpkit.server$eval19781$fn__19851$G__19772__19858.invoke(server.clj:96)
	at taoensso.sente.server_adapters.http_kit.HttpKitServerChanAdapter.ring_req__GT_server_ch_resp(http_kit.clj:25)
	at taoensso.sente$make_channel_socket_server_BANG_$fn__21615.invoke(sente.cljc:606)
	at muuntaja.middleware$wrap_params$fn__8119.invoke(middleware.clj:52)
	at muuntaja.middleware$wrap_format$fn__8123.invoke(middleware.clj:73)
	at everclear.middleware$wrap_formats$fn__9289.invoke(middleware.clj:41)
	at ring.middleware.anti_forgery$wrap_anti_forgery$fn__6955.invoke(anti_forgery.clj:94)
	at ring.middleware.params$wrap_params$fn__9021.invoke(params.clj:67)
	at ring.middleware.keyword_params$wrap_keyword_params$fn__8807.invoke(keyword_params.clj:53)
	at reitit.ring$ring_handler$fn__24478.invoke(ring.cljc:326)
	at clojure.lang.AFn.applyToHelper(AFn.java:154)
	at clojure.lang.AFn.applyTo(AFn.java:144)
	at clojure.lang.AFunction$1.doInvoke(AFunction.java:31)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.lang.Var.invoke(Var.java:384)
	at ring.middleware.reload$wrap_reload$fn__4448.invoke(reload.clj:39)
	at selmer.middleware$wrap_error_page$fn__4463.invoke(middleware.clj:18)
	at prone.middleware$wrap_exceptions$fn__4704.invoke(middleware.clj:159)
	at ring.middleware.flash$wrap_flash$fn__8160.invoke(flash.clj:39)
	at ring.middleware.session$wrap_session$fn__8605.invoke(session.clj:108)
	at ring.adapter.undertow.middleware.session$wrap_undertow_session$fn__8711.invoke(session.clj:88)
	at ring.middleware.keyword_params$wrap_keyword_params$fn__8807.invoke(keyword_params.clj:53)
	at ring.middleware.nested_params$wrap_nested_params$fn__8865.invoke(nested_params.clj:89)
	at ring.middleware.multipart_params$wrap_multipart_params$fn__8997.invoke(multipart_params.clj:171)
	at ring.middleware.params$wrap_params$fn__9021.invoke(params.clj:67)
	at ring.middleware.cookies$wrap_cookies$fn__8484.invoke(cookies.clj:214)
	at ring.middleware.absolute_redirects$wrap_absolute_redirects$fn__9209.invoke(absolute_redirects.clj:47)
	at ring.middleware.resource$wrap_resource_prefer_resources$fn__9057.invoke(resource.clj:25)
	at ring.middleware.content_type$wrap_content_type$fn__9157.invoke(content_type.clj:34)
	at ring.middleware.default_charset$wrap_default_charset$fn__9181.invoke(default_charset.clj:31)
	at ring.middleware.not_modified$wrap_not_modified$fn__9123.invoke(not_modified.clj:61)
	at ring.middleware.x_headers$wrap_x_header$fn__8747.invoke(x_headers.clj:22)
	at ring.middleware.x_headers$wrap_x_header$fn__8747.invoke(x_headers.clj:22)
	at ring.middleware.x_headers$wrap_x_header$fn__8747.invoke(x_headers.clj:22)
	at everclear.middleware$wrap_internal_error$fn__9283.invoke(middleware.clj:20)
	at ring.adapter.undertow$undertow_handler$fn$reify__42283.handleRequest(undertow.clj:33)
	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:370)
	at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
	at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
	at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1558)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1449)
	at java.base/java.lang.Thread.run(Thread.java:831)
I get this error in the developer console by the way:
sente.cljc:1045 WebSocket connection to '<ws://localhost:3000/chsk?client-id=1aff9efa-b158-4247-84f8-4b21936a9085&amp;csrf-token=zmd0tN%2BySX0N%2F58zu%2FFAg%2BpLKnac5jbJGxWK8kPbx6uTYxqjjimzsf4C9%2B%2FZE%2BwkC2%2F8ppHEHT9tX9XO>' failed: 
eval @ sente.cljc:1045
core.cljs:159 ERROR [taoensso.sente:1058] - WebSocket error: [object Event]
eval @ core.cljs:159

Endre Bakken Stovner 2021-05-11T10:08:16.018400Z

These are the relevant lines mentioned in the stack trace (from middleware.clj):

17	(defn wrap-internal-error [handler]
    18	  (fn [req]
    19	    (try
    20	      (handler req)
    21	      (catch Throwable t
    22	        (log/error t (.getMessage t))
    23	        (error-page {:status 500
    24	                     :title "Something very bad has happened!"
    25	                     :message "We've dispatched a team of highly trained gnomes to take care of the problem."})))))
    26
    27	(defn wrap-csrf [handler]
    28	  (wrap-anti-forgery
    29	    handler
    30	    {:error-response
    31	     (error-page
    32	       {:status 403
    33	        :title "Invalid anti-forgery token"})}))
    34
    35
    36	(defn wrap-formats [handler]
    37	  (let [wrapped (-&gt; handler wrap-params (wrap-format formats/instance))]
    38	    (fn [request]
    39	      ;; disable wrap-formats for websockets
    40	      ;; since they're not compatible with this middleware
    41	      ((if (:websocket? request) handler wrapped) request))))

alexmiller 2021-05-11T13:46:01.020Z

re the original question, you had it. multimethod methods can be extended after the fact without changing the defmulti. case will require all cases to be defined at the same place.

1
alexmiller 2021-05-11T13:47:11.020200Z

no, maps only. the syntax would be pretty ugly for sets #:a.b#{:foo 123} - that seemed bad :)

alexmiller 2021-05-11T13:47:31.020400Z

still sitting on the fence about vectors

valerauko 2021-05-11T15:32:24.021Z

is there anything as simple to use as slurp/spit for binary data?

borkdude 2021-05-11T15:33:48.021200Z

FileOutputStream perhaps?

borkdude 2021-05-11T15:35:51.021700Z

java.nio.file.Files has readAllBytes

borkdude 2021-05-11T15:36:22.021900Z

it's also available in this library: https://github.com/babashka/fs/blob/05d392933a4e6fe0e0c3fa002c1bdeeccc995801/src/babashka/fs.cljc#L527

borkdude 2021-05-11T15:36:50.022600Z

and <http://clojure.java.io/copy|clojure.java.io/copy> does support writing a byte array to a file

valerauko 2021-05-11T15:37:37.023600Z

my use case would be reading a binary input stream (ring request body), checking how long the contents are and writing it into a file

valerauko 2021-05-11T15:38:33.024Z

this is really easy with text data with slurp and spit but binary data not so much

valerauko 2021-05-11T15:41:05.025Z

jio/copy might be the way to go hmm

alexmiller 2021-05-11T15:58:27.025500Z

you could just use the http://java.io inputstreams for this kind of thing

valerauko 2021-05-11T16:02:29.025900Z

i know but i hoped there was something as simple as slurp/spit šŸ˜ž

2021-05-11T16:03:35.026300Z

slurp/spit is easy, but not simple

šŸ™‚ 1
1
piyer 2021-05-11T20:09:16.030500Z

Logging in java is such a frustration. I imported clj-http that messed with my current logging and logs stopped showing up on my cider. Is there a way to turn off the logging from clj-http?

seancorfield 2021-05-11T20:17:15.031200Z

@munichlinux What are you currently using for logging?

piyer 2021-05-11T20:35:14.031600Z

@seancorfield here is my setup:

[org.apache.logging.log4j/log4j-api "2.14.1"]

                 [org.apache.logging.log4j/log4j-core "2.14.1"]
                 [org.apache.logging.log4j/log4j-jcl "2.14.1"]
                 [org.apache.logging.log4j/log4j-jul "2.14.1"]
                 [org.apache.logging.log4j/log4j-1.2-api "2.14.1"]

piyer 2021-05-11T20:38:20.031700Z

here is my log4j2.xml:

&lt;?xml version= "1.0" encoding= "UTF-8" ?&gt;
&lt;Configuration monitorInterval= "10" &gt;
  &lt;Appenders&gt;
    &lt;!-- console output --&gt;
    &lt;Console name= "Console" target= "SYSTEM_OUT" &gt;
      &lt;PatternLayout pattern= "[%level] - %d %logger %m%n%throwable" /&gt;
    &lt;/Console&gt;
  &lt;/Appenders&gt;
  &lt;Loggers&gt;
    &lt;Logger name= "io.grpc.netty.shaded.io" level= "ERROR" &gt;
      &lt;AppenderRef ref= "Console" /&gt;
    &lt;/Logger&gt;
    &lt;Logger name="org.apache.http" level="OFF" &gt;
    &lt;/Logger&gt;
    &lt;Root level= "all" includeLocation= "false" &gt;
      &lt;AppenderRef ref= "Console" level= "DEBUG" /&gt;
      &lt;AppenderRef ref= "Console" level= "ERROR" /&gt;
      &lt;AppenderRef ref= "Console" /&gt;
    &lt;/Root&gt;
  &lt;/Loggers&gt;
&lt;/Configuration&gt;

seancorfield 2021-05-11T20:43:58.031900Z

And youā€™re using tools.logging to do your actual logging, yes?

seancorfield 2021-05-11T20:44:41.032100Z

Read over this section: https://github.com/clojure/tools.logging/#selecting-a-logging-implementation

seancorfield 2021-05-11T20:46:08.032400Z

What I believe is happening is that previously, tools.logging was picking up log4j2 by default but when you introduced clj-http, it depends on commons logging which tools.logging ā€œprefersā€, so you need to explicitly tell it to use log4j2 anyway (via the JVM option described in that link).

Kieran D'Mello 2021-05-11T20:47:06.033500Z

Hi, im having a bit of an issue calling a package private function from a base class. After doing a bunch of googling it seems others have had some problems too and was wondering if anyone had a solution?

piyer 2021-05-11T20:47:28.033600Z

@seancorfield yes using tools.logging.

piyer 2021-05-11T21:00:12.033800Z

@seancorfield I added that to :repl section

:repl {:jvm-opts ["-Dclojure.tools.logging.factory=clojure.tools.logging.impl/log4j2-factory"]}

piyer 2021-05-11T21:00:21.034Z

that did not do the magic either.

seancorfield 2021-05-11T21:06:48.034300Z

Are you sure that however you are starting up your Clojure process is using that? (profile/alias)

seancorfield 2021-05-11T21:07:37.035Z

@kierand Can you provide a bit more context? That doesnā€™t sound like a Clojure problemā€¦?

Kieran D'Mello 2021-05-11T21:09:48.035400Z

so i have the following code

(def pca
  (-&gt; (PublicClientApplication/builder client-id)
      (.authority auth)
      (.build)))

Kieran D'Mello 2021-05-11T21:11:03.036400Z

but .authority is inherited from an abstract class

Kieran D'Mello 2021-05-11T21:11:28.036900Z

so when i try to call it i get Reflection warning, clojure_ad_test/core.clj:22:7 - call to method authority on com.microsoft.aad.msal4j.PublicClientApplication$Builder can't be resolved (argument types: unknown).

seancorfield 2021-05-11T21:12:18.037700Z

That says it canā€™t figure out the type of auth so it doesnā€™t know what method to call.

seancorfield 2021-05-11T21:12:42.038300Z

Youā€™ll have to type hint auth, either where you declare it, or inline.

seancorfield 2021-05-11T21:13:14.038700Z

Try (.authority ^String auth)

Kieran D'Mello 2021-05-11T21:13:58.039300Z

i tried that but i get the same errror

Kieran D'Mello 2021-05-11T21:14:24.039700Z

except type unknown is now java.lang.String

Kieran D'Mello 2021-05-11T21:15:58.040500Z

fyi those docs are wrong the actual signature of builder is public static class Builder extends com.microsoft.aad.msal4j.AbstractClientApplicationBase.Builder&lt;PublicClientApplication.Builder&gt;

Kieran D'Mello 2021-05-11T21:21:32.041200Z

Reflection warning, clojure_ad_test/core.clj:23:7 - call to method authority on com.microsoft.aad.msal4j.PublicClientApplication$Builder can't be resolved (argument types: java.lang.String). Reflection warning, clojure_ad_test/core.clj:24:7 - reference to field build can't be resolved. Execution error (IllegalArgumentException) at clojure.main/main (main.java:40). No matching method authority found taking 1 args for class com.microsoft.aad.msal4j.PublicClientApplication$Builder

piyer 2021-05-11T21:21:34.041400Z

The only problem is on the cider repl. I do see the logs in nrepl-server

Kieran D'Mello 2021-05-11T21:21:38.041600Z

thats the entire stack trace

seancorfield 2021-05-11T21:27:36.042200Z

On Clojure 1.8, we get a different error:

(! 1452)-&gt; clj -Sdeps '{:deps {com.microsoft.azure/msal4j {:mvn/version "1.0.0"}}}' -A:1.8
Clojure 1.8.0
user=&gt; (import 'com.microsoft.aad.msal4j.PublicClientApplication)
com.microsoft.aad.msal4j.PublicClientApplication
user=&gt; (let [b (PublicClientApplication/builder "foo")] (.authority b "bar"))
IllegalArgumentException Can't call public method of non-public class: public com.microsoft.aad.msal4j.ClientApplicationBase$Builder com.microsoft.aad.msal4j.ClientApplicationBase$Builder.authority(java.lang.String) throws java.net.MalformedURLException  clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:88)
user=&gt; ^D
(! 1453)-&gt; clj -Sdeps '{:deps {com.microsoft.azure/msal4j {:mvn/version "1.0.0"}}}' -A:1.10
Clojure 1.10.3
user=&gt; (import 'com.microsoft.aad.msal4j.PublicClientApplication)
com.microsoft.aad.msal4j.PublicClientApplication
user=&gt; (let [b (PublicClientApplication/builder "foo")] (.authority b "bar"))
Execution error (IllegalArgumentException) at user/eval138 (REPL:1).
No matching method authority found taking 1 args for class com.microsoft.aad.msal4j.PublicClientApplication$Builder
user=&gt; 
I wonder if @ghadi can shed some light on this?

seancorfield 2021-05-11T21:29:00.043Z

(ISTR this is an area where Clojure has made some changes over the years but Iā€™m cloudy on what they were)

ghadi 2021-05-11T21:29:02.043100Z

can someone link to the javadocs for this target class?

seancorfield 2021-05-11T21:29:09.043300Z

Linked above.

1
seancorfield 2021-05-11T21:30:12.043700Z

Then ask in #cider ā€” I havenā€™t used that for years so I canā€™t help you, sorry.

šŸ‘ 1
2021-05-11T21:49:56.044600Z

The is an ask.clojure for this issue

2021-05-11T21:50:01.044700Z

There is

seancorfield 2021-05-11T21:54:52.045400Z

I thought it sounded a bit familiar. Iā€™ve upvoted that ask issue.

alexmiller 2021-05-11T22:09:28.046600Z

This is an old problem (https://clojure.atlassian.net/browse/CLJ-1243 ) that really links back to an even older still open issue in Java https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4283544

2021-05-11T22:14:02.046700Z

Yech, what a mess

Kieran D'Mello 2021-05-11T22:26:57.047400Z

yeah i went through all of those issues and they all seem to end at a dead end

2021-05-11T22:38:51.047800Z

if you are just looking for a work around to make it work something like

(import 'com.microsoft.aad.msal4j.PublicClientApplication)

(def authority
  (.findVirtual
   (java.lang.invoke.MethodHandles/lookup)
   com.microsoft.aad.msal4j.PublicClientApplication$Builder
   "authority"
   (java.lang.invoke.MethodType/methodType
    com.microsoft.aad.msal4j.ClientApplicationBase$Builder
    [String])))

(let [b (PublicClientApplication/builder "foo")]
  (.invokeWithArguments authority [b "foo"]))
should work

Kieran D'Mello 2021-05-11T22:46:56.048600Z

yep that works i had to make small change from com.microsoft.aad.msal4j.ClientApplicationBase$Builder to com.microsoft.aad.msal4j.AbstractClientApplicationBase$Builder but i can call the method.

Kieran D'Mello 2021-05-11T22:46:59.048800Z

Thanks so much!!

dpsutton 2021-05-11T22:48:14.049300Z

wow. this one was kinda sounding impossible to get the Clojure compiler to output the correct bytecode

ghadi 2021-05-11T22:57:28.050100Z

thereā€™s a method selection bug

ghadi 2021-05-11T22:57:46.050600Z

will try to understand the behavior and documentat

Kieran D'Mello 2021-05-11T23:03:01.051300Z

so just out of curiousity - is this something that clojure can fix or something that has to be fixed at a java level?

2021-05-11T23:08:13.053300Z

it is kind of complicated

2021-05-11T23:08:49.054Z

there are kind of two ways method invoking like (.authority b "foo") can get compiled

2021-05-11T23:09:29.054700Z

one way is without reflection, which the compiler does if it knows all the types, but there appears to be a clojure bug somewhere so it is failing to do that

2021-05-11T23:10:35.055800Z

if a method call cannot be compiled without reflection, the compiler generates code that will do a reflective call at runtime, which would hit the underlying java issue

Kieran D'Mello 2021-05-11T23:27:20.056Z

Ah so it's trying reflection because it should know the types but then the bug stops it from getting the abstract class it inherits from?

2021-05-11T23:36:05.057300Z

Would it be possible to point a function at a directory on my computer, have it find all of the image files, and then create a map according to this schema?