So this was what you helped me with, yesterday, @dpsutton and @seancorfield https://github.com/PEZ/taplet I notice that the tests are not as predictable as I would expect them to be. It sometimes seem like they write over each other’s atoms, but since they are locals that really can’t be happening. Anyway, I don’t understand why the tests get brittle. Not planning to put this in CI, though, so it is OK for now. Anyway, I have a bunch of questions about macros now, so will probably return here. Thanks again for the super duper support!
Hello. #vscode channel looks like forgotten, so sorry for asking here - is there any usable Clojure code formatter for VSCode?
Try #calva
Oh, I see you've already asked there.
Can't help sorry, not a vscode user.
Thanks, I used it several years before it becames unusable due to unswitchible lsp integration. Now I installed Clover, clj-condo linter and only one thing I need is formatter.
Hey folks, got a question for people who know there way around Java interop
I am using openhft Java runtime compiler to compile Java classes dynamically
Im getting to the compiling part just fine
But the class file contains Java interfaces and other class definitions etc
Now I’m wondering how I can load these files and symbols from the Java project into my clojure namespace to make it accessible to the compiler
I guess I need to put them on the classpath somehow?
Just to be curious, what issues you had with Calva LSP(clojure-lsp)? Maybe we can improve that
I think hacking Calva-fmt to accept your config is a way to do it.
@dev-hartmann a convention in some clojure projects is to have a directory classes
where you emit these classes and then put classes
in your :paths
in deps.edn. For lein this directory is called target
and it is on the classpath by default
Thanks, I'l try this way.
Thx @borkdude I guess I can get maven to export the classes from the other project and cp them into a classes folder in my clojure project
or just add the other path to your :paths
:local/root
+ adding deps.edn
in that project might also work, if the path is not within the project
Ah, interesting I’ll try
The other project is a pure Java project
I‘ll try adding it to my paths in deps.edn and maybe it works then 😎
@dev-hartmann if the other project has a pom.xml
and the classes are on the classpath of that pom.xml
, then you can use :local/root
to add that project
Yes it has a pom.xml
Nice, I’ll read up on :local/root, thank you very much
Ah got it
I can import the complete project as a dependency but specifiying it is local 👌:skin-tone-4:
That’s awesome
Wow, seems to work
🤯
Now I just need to add the company private nexus to use everything
That’s just brilliant, thx a lot @borkdude !
Sure. Join #tools-deps if you have any other questions about this
Thx, will do 👍:skin-tone-4:
what would be a good way to block a thread until a channel (or atom) holds a specific value?
invert the problem, only put expected value on the channel and just use <!!
?
put a filter transducer on the channel and just take
you can use a watch on an atom
(defn when-is [a v] (let [k (Object.) p (promise)] (add-watch a (fn [a k ov nv] (when (= nv v) (deliver p true) (remove-watch a k)))) (when (= @a v) (deliver p true) (remove-watch a k)) @p)) ;; the order of args to the watch fn is likely wrong
and I forgot to deref the promise
regarding the add-watch argument order, I've found kron
to be helpful as a mnemonic (Key/Ref/Old/New)
Java 16 is out and I presume it works with Clojure. I know it brings strong encapsulation by default, so my question is: How does this impact Clojure ? https://jdk.java.net/16/release-notes
It does work with Clojure
Does not really impact Clojure much
Which part of the article you linked describes the part you mention as "string encapsulation"? Are you referring to the part of the linked document titled "Improve Encoding of TLS Application-Layer Protocol Negotiation (ALPN) Values" ?
Strong* - typo, sorry
JEP 396: Strongly Encapsulate JDK Internals by Default (JDK-8256299)
core-libs
Strongly encapsulate all internal elements of the JDK by default, except for critical internal APIs such as sun.misc.Unsafe. Allow end users to choose the relaxed strong encapsulation that has been the default since JDK 9.
With this change, the default value of the launcher option --illegal-access is now deny rather than permit. As a consequence, existing code that uses most internal classes, methods, or fields of the JDK will fail to run. Such code can be made to run on JDK 16 by specifying --illegal-access=permit. That option will, however, be removed in a future release.
For further details, please see JEP 396.
I haven't tried, but wonder if this is a release where some things that were warnings in previous JDKs become errors, that might affect a few libraries here and there that issued warnings with earlier JDKs.
no fancy compiler stuff related to record classes?
Even if so, that issue is not Clojure-specific, I believe -- just that certain JVM code will need explicit permissions that they didn't need before.
records are useful for java devs but boooring for Clojure devs
we already have boilerplate-free, immutable, transparent state carriers: maps
I do not care about the language level stuff in JDK 16, but the VM level stuff is absolutely massive
high-level SIMD API (Vector API, incubating) call C functions directly without writing a lick of JNI (Foreign Linker API, incubating)
sure, I was thinking more in terms of how the Clojure compiler/runtime works, not so much the API layer, but I don’t know nearly enough about how Clojure is implemented to know whether something like, say, pattern matching of records, can provide any value (ex: like for optimizing cond
or something)
> call C functions directly without writing a lick of JNI does this bring a Python-like FFI for C libs for Clojure a bit closer?
yeah, stay tuned, I'm cooking up something nice
niiice :) hope it works with GraalVM as well, can add it to bb and have more lib reach :)
it won't 🙂
graalvm is java11 based tops
GraalVM will update to 16 /17 eventually, but are there any technical reasons it shouldn't work?
I'm assuming you're doing something byte-code emitting related right?
yeah right now I’m spinning dynamic IFn -> MethodHandle proxies
I think it will happen with 17 - the next LTS
Could have other impls possible
ZGC max pause times from 10ms -> 1ms is very exciting too (heap size agnostic!)
TIL re: Java 16 — public constructors for the primitive wrapper classes (`Long`, Double
, Integer
, etc) have been deprecated since Java 9 (searches all his code, finds no such uses 😅 ).
do you mean they have been removed finally?
Not yet, but in Java 16 you’ll get warnings on their usage. And they will go away eventually. I’d just totally missed they’d been deprecated for so long!
oh i didn't realize 16 started emitting warnings about them. i knew they were deprecated for a while
I think they've been linting that for years if you check deprecation warnings
pretty sure we did a pass through Clojure source 2-3 years ago to fix up a couple
but you won't see it through Clojure interop, right?
(maybe clj-kondo can fix this)
oh, you mean if you used Clojure to invoke the Java constructor?
yes
should be able to lint that, I don't think you'd see it otherwise
\
you mean, should be able to lint that, who?
java, clojure, clj-kondo?
clj-kondo
like https://github.com/dakrone/cheshire/blob/master/test/cheshire/test/core.clj#L437
ok, I'll add an issue for it
just grepping a few quick examples, surely there are more
the clojure reflector already checks for "canAccess", is this something it could do too? or too much perf overhead / info not available in the JVM?
what I've found in the past is that canAccess will only give feedback when it's set to "deny", so it probably won't help until they actually turn it off
I don't think we want to be in the business of checking for specific invocations inside the reflector
linting seems like the right level of check to me
I agree about not adding specifics. Was just wondering if https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Constructor.html had a field "deprecated" or something, but it hasn't.
nah, I don't think there is any way to tell this programmatically
I mean I guess you could check for a Deprecated annotation on the method
I'll probably use that to generate a list of deprecated methods for linting
https://download.java.net/java/early_access/jdk16/docs/api/java.base/java/lang/Boolean.html#%3Cinit%3E(boolean) - you can see that the info is there and I think that's retrievable
the annotation has to be marked to be marked for runtime retention but that one should be
so, I'll change my answer - yes, it's possible to programmatically detect this in the reflector :)
should we is a separate question :)
pushing things to lint-time is better for performance ;)
yeah, that would need assessment. I would not be opposed to an ask.clojure question about this, might generally be a useful thing, at least as an option
surprising that I do not remember anyone asking about this before now
You tend to be first on about 50% of things like this, I believe 🙂
afaik clojure itself doesn't even warn about deprecated vars?
seems like a semi-obvious idea that has been available since Java 5, so basically forever in Clojure release lifetime
Oh does kondo not warn on this? Cider nrepl has done this for a while and it’s quite nice. I’m doing a month without nrepl and didn’t look into this yet
there definitely is a ticket about Clojure :)
feel free to vote at https://ask.clojure.org/index.php/4625/make-use-of-deprecated-namespaces-vars-easier-to-spot
@dpsutton yes, kondo warns, but clojure doesn't
I didn't expect that (binding [*read-eval* false] (load "some/ns"))
would still execute a contained #=(println 42)
I guess there's no built-in way to forbid read-eval literals in clojure namespaces?
oh what a weird thing: (var + nonsense)
-> #'clojure.core/+
warns on clojure deprecations or java deprecations or both?
and so threading last into a private function call at the repl is quite surprising at first. (->> foo #'ns/private-fn)
yields ns/private-fn
currently warns on deprecated vars. I just made an issue for deprecated methods/constructors, but it doesn't do that yet
i got a bit turned around on which deprecations i was thinking of 🙂
Hmm:
user=> (binding [*read-eval* false] (read-string "#=(println :foo)"))
Execution error at user/eval138 (REPL:1).
EvalReader not allowed when *read-eval* is false.
user=> (binding [*read-eval* false] (load-string "#=(println :foo)"))
:foo
nil
if you're loading code, does it matter if there are the #=
forms? it's executing everything right? you're trusting the source
this slightly pre-dates my involvement with Clojure core, but my recollection is that read-eval is there to prevent read eval when reading untrusted data with read. Code on your classpath (loaded by load) is presumably there because you put it there and it is considered to be trusted and thus outside the scope of read-eval
as dpsutton says, it's not just going to read, it's going to eval as well
@borkdude yeah precisely, it's that difference that I found surprising. TIL about load-string
btw!
yeah that reasoning makes sense, in the end one is also evaling a string when doing load
, require
, etc.
But the difference might be considered quirky.
I ended up using tools.reader. It offers its own *read-eval*
var; if binding it to false while content some contents one will get an exception, as I was seeking
that should be the same as using clojure.core/read
don't know why you need tools.reader for that
you're right, it's not an essential part. In my project tools.reader is used for all reading needs though
And [clojure.core/*read-eval* false]
in combination with tools.reader does not result in errors being thrown, but in nil values being read
can i ask what problem you're trying to solve?
Linting against #=()
syntax, I've seen it in production projects and as I saw it, it wasn't either a good thing or something without viable alternatives
Might be something we could add to clj-kondo as well
i was just wondering if grasp could identify them
As in: when you enable the linter, warn
This is easier with clj-kondo or let's say, just rewrite-clj for example. Grasp assumes that your code already has been parsed correctly
Or in fact, I do think grasp will throw when it encounters one of those.
Similar to how bb throws:
$ bb -e '#=(+ 1 2 3)'
----- Context ------------------------------------------------------------------
1: #=(+ 1 2 3)
^--- Read-eval not allowed. Use the `:read-eval` option
You can also parse all your code with edamame (which is one level below grasp / sci)
to do the same
it's built on top of tools.reader
Hi all, I am having a strange issue with spec instrumentation that throws where it should not...
What is peculiar is that the instrumentation exception show this :via
(notice the repetition):
[::report/report-identifiers
::report/report-identifiers
::report/image-descriptors
::report/image-descriptor
::report/image-id]
But my ::report/report-identifiers
looks like
(s/def ::report-identifiers
(s/keys :req [::id
::version-id]))
I am having trouble even debugging it...cause the registry seems to return the above spec definition but the instrumentation check then fails...do you folks have any hint?