Fork me on GitHub
#clojure
<
2024-04-30
>
roklenarcic10:04:05

I’m writing some code in Java that is a class that has references that hold Clojure persistent datastructures. When defining this object’s hashcode and equals, when should I use clojure.lang.Util hasheq and equiv and when should I just use the java Object ones?

thomas11:04:18

When I try and run the tests from the Zach Tellman's virgil library [https://github.com/ztellman/virgil] I get the following warning (on Java 11 and on later versions it is a failure):

recompiling all files in ["/tmp/virgil"]
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by clojure.lang.InjectedInvoker/0x00000008000acc40 (file:/Users/thomas/.m2/repository/org/clojure/clojure/1.11.3/clojure-1.11.3.jar) to method com.sun.tools.javac.api.JavacTool.getStandardFileManager(javax.tools.DiagnosticListener,java.util.Locale,java.nio.charset.Charset)
WARNING: Please consider reporting this to the maintainers of clojure.lang.InjectedInvoker/0x00000008000acc40
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Any ideas how I can fix this?

oyakushev11:04:19

Virgil's original repo is not maintained anymore. Please try the maintained fork: https://github.com/clojure-goes-fast/virgil. Note that it doesn't have a lein plugin, you are supposed to add it as a runtime dependency and invoke manually (see README)

1
thomas11:04:04

thank you @U064X3EF3 and @U06PNK4HG

❤️ 1
seancorfield23:05:30

FYI: Zach just transferred virgil to clj-commons -- @U06PNK4HG would you be interested in becoming the official maintainer under the clj-common org, and bringing the underlying repo up to date with your fork? Happy to discuss further in #CE1A21MPF

Ingy döt Net11:04:58

I have a function called compile and another called compile-debug and determine which to call by the value of an atom I set from a CLI -d option. They are the same but the second one can print debug info for any or all of my 7 stages of compilation. I'd rather not do the checking at runtime. I was wondering if I could turn this into a macro that expanded to the right thing at runtime. It seems that I'd have to set the atom before requiring the library with the compile function in it. Is that right?

p-himik12:04:28

These two statements contradict each other: > I'd rather not do the checking at runtime. > a macro that expanded to the right thing at runtime since such a macro would still rely on a run-time check. > It seems that I'd have to set the atom before requiring the library with the compile function in it. > Is that right? Yes. > I set from a CLI -d option. If you switch to Java properties or environment variables (both of which you can use with CLIs), you can make it work without having to be careful about namespace loading order.

Ingy döt Net12:04:33

I meant I'd rather not have compile function that checks for the debugging of each stage at runtime, for every invocation of the compile function. I want to macro expand the function once at runtime to DTRT. I already need to decide with of the 2 highly similar functions to call at runtime.

Ingy döt Net12:04:50

I'm asking because I need to add other options to this function and don't want a matrix of similar functions... I think for now I'll just collapse it to one compile function that checks behavior at runtime. iow, not prematurely optimize until it's an issue

p-himik12:04:33

You don't have to decide every time:

(if debug?
  (defn compile [...] ... debug impl ...)
  (defn compile [...] ... regular impl ...)

Ingy döt Net12:04:34

https://github.com/yaml/yamlscript/blob/main/core/src/yamlscript/compiler.clj#L29-L96 are the functions, called here: https://github.com/yaml/yamlscript/blob/main/ys/src/yamlscript/cli.clj#L280-L284 Getting rid of the -d option is not something I want to do. I use it constantly. I see what you are saying but what I want to get to is to DRY out compile to one function, not 2. And I'm about to add more options. I was thinking a macro might be useful to expand to the right thing, but likely it would be more convoluted to read. I guess for any new options I can just add them to the debug version, and stay at 2 implementations: compile-normal and compile-with-options.

p-himik12:04:39

An alternative is to start being careful avoid namespace loading. One more or less trivial solution is to have a "wrapper" namespace that's the main entry point and that doesn't use :require to load other namespace but rather uses requiring-resolve to require, resolve, and call some other entry point after all CLI options have been parsed and all global flags have been set. I don't have time at the moment to properly study your code, but it seems that you're already passing opts around so I don't know what that global atom that you've mentioned is or why you'd need it. Passing opts around is probably the most direct, simple, and robust way to handle things. To avoid repeating things across compile implementation, you can employ regular refactoring techniques - you can combine it into a single function that checks opts itself or you can split the functionality into many smaller functions that compile and compile-debug would call, maybe conditionally.

1
Ingy döt Net15:04:32

I'll look into the requiring-resolve technique at some point. I don't use atoms much, but keeping the parsed CLI options in an atom mapping to be accessed from anywhere in the code without needing to refactor that code feels right to me. And yes, there is a little more refactoring I can do to dry out the compile and compile-with-special-options functions. Thanks for the help 🙂