Fork me on GitHub
#clojure
<
2021-03-17
>
pez08:03:50

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!

ivana11:03:57

Hello. #vscode channel looks like forgotten, so sorry for asking here - is there any usable Clojure code formatter for VSCode?

dharrigan11:03:24

Oh, I see you've already asked there.

dharrigan11:03:35

Can't help sorry, not a vscode user.

ivana11:03:09

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.

ericdallo11:03:56

Just to be curious, what issues you had with Calva LSP(clojure-lsp)? Maybe we can improve that

pez11:03:44

I think hacking Calva-fmt to accept your config is a way to do it.

1
ivana11:03:30

Thanks, I'l try this way.

dev-hartmann11:03:23

Hey folks, got a question for people who know there way around Java interop

dev-hartmann11:03:01

I am using openhft Java runtime compiler to compile Java classes dynamically

dev-hartmann11:03:27

Im getting to the compiling part just fine

dev-hartmann11:03:52

But the class file contains Java interfaces and other class definitions etc

dev-hartmann11:03:35

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

dev-hartmann11:03:52

I guess I need to put them on the classpath somehow?

borkdude11:03:08

@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

metal 1
dev-hartmann12:03:49

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

borkdude12:03:29

or just add the other path to your :paths

borkdude12:03:54

:local/root + adding deps.edn in that project might also work, if the path is not within the project

dev-hartmann12:03:09

Ah, interesting I’ll try

dev-hartmann12:03:25

The other project is a pure Java project

dev-hartmann12:03:56

I‘ll try adding it to my paths in deps.edn and maybe it works then 😎

borkdude12:03:17

@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

dev-hartmann12:03:44

Yes it has a pom.xml

dev-hartmann12:03:12

Nice, I’ll read up on :local/root, thank you very much

dev-hartmann12:03:26

I can import the complete project as a dependency but specifiying it is local 👌:skin-tone-4:

dev-hartmann12:03:33

That’s awesome

dev-hartmann12:03:40

Wow, seems to work

dev-hartmann12:03:47

Now I just need to add the company private nexus to use everything

dev-hartmann12:03:09

That’s just brilliant, thx a lot @borkdude !

borkdude12:03:52

Sure. Join #tools-deps if you have any other questions about this

dev-hartmann12:03:52

Thx, will do 👍:skin-tone-4:

restenb15:03:52

what would be a good way to block a thread until a channel (or atom) holds a specific value?

restenb15:03:38

invert the problem, only put expected value on the channel and just use <!! ?

alexmiller15:03:09

put a filter transducer on the channel and just take

👍 2
hiredman16:03:25

you can use a watch on an atom

hiredman16:03:00

(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

jjttjj16:03:13

regarding the add-watch argument order, I've found kron to be helpful as a mnemonic (Key/Ref/Old/New)

hiredman16:03:28

and I forgot to deref the promise

alexmiller16:03:24

It does work with Clojure

alexmiller16:03:40

Does not really impact Clojure much

👍 1
Jeff Evans16:03:48

no fancy compiler stuff related to record classes?

ghadi16:03:22

records are useful for java devs but boooring for Clojure devs

Jeff Evans16:03:56

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)

ghadi16:03:56

we already have boilerplate-free, immutable, transparent state carriers: maps

ghadi16:03:42

I do not care about the language level stuff in JDK 16, but the VM level stuff is absolutely massive

ghadi16:03:25

high-level SIMD API (Vector API, incubating) call C functions directly without writing a lick of JNI (Foreign Linker API, incubating)

borkdude16:03:02

> 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?

ghadi16:03:15

yeah, stay tuned, I'm cooking up something nice

borkdude16:03:44

niiice :) hope it works with GraalVM as well, can add it to bb and have more lib reach :)

ghadi16:03:54

it won't 🙂

delaguardo16:03:06

graalvm is java11 based tops

borkdude16:03:33

GraalVM will update to 16 /17 eventually, but are there any technical reasons it shouldn't work?

Eugen16:03:04

I think it will happen with 17 - the next LTS

borkdude16:03:52

I'm assuming you're doing something byte-code emitting related right?

ghadi16:03:01

yeah right now I’m spinning dynamic IFn -> MethodHandle proxies

ghadi16:03:35

Could have other impls possible

jjttjj16:03:08
replied to a thread:

The latest inside java podcast https://inside.java/podcast/ gave a nice, easy to understand overview of the new stuff in java 16

👍 2
ghadi17:03:23

ZGC max pause times from 10ms -> 1ms is very exciting too (heap size agnostic!)

seancorfield17:03:49

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 😅 ).

🙂 5
dpsutton17:03:21

do you mean they have been removed finally?

seancorfield17:03:48

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!

dpsutton17:03:24

oh i didn't realize 16 started emitting warnings about them. i knew they were deprecated for a while

alexmiller17:03:23

I think they've been linting that for years if you check deprecation warnings

alexmiller17:03:24

pretty sure we did a pass through Clojure source 2-3 years ago to fix up a couple

borkdude17:03:10

but you won't see it through Clojure interop, right?

borkdude17:03:51

(maybe clj-kondo can fix this)

alexmiller17:03:10

oh, you mean if you used Clojure to invoke the Java constructor?

alexmiller17:03:43

should be able to lint that, I don't think you'd see it otherwise

borkdude17:03:12

you mean, should be able to lint that, who?

borkdude17:03:30

java, clojure, clj-kondo?

borkdude17:03:52

ok, I'll add an issue for it

alexmiller17:03:25

just grepping a few quick examples, surely there are more

borkdude17:03:44

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?

alexmiller17:03:24

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

alexmiller17:03:29

I don't think we want to be in the business of checking for specific invocations inside the reflector

alexmiller17:03:28

linting seems like the right level of check to me

borkdude17:03:46

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.

alexmiller17:03:32

nah, I don't think there is any way to tell this programmatically

alexmiller17:03:58

I mean I guess you could check for a Deprecated annotation on the method

borkdude17:03:54

I'll probably use that to generate a list of deprecated methods for linting

alexmiller17:03:41

the annotation has to be marked to be marked for runtime retention but that one should be

alexmiller17:03:26

so, I'll change my answer - yes, it's possible to programmatically detect this in the reflector :)

alexmiller17:03:49

should we is a separate question :)

borkdude17:03:13

pushing things to lint-time is better for performance ;)

alexmiller17:03:46

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

alexmiller17:03:41

surprising that I do not remember anyone asking about this before now

andy.fingerhut17:03:11

You tend to be first on about 50% of things like this, I believe 🙂

alexmiller17:03:19

seems like a semi-obvious idea that has been available since Java 5, so basically forever in Clojure release lifetime

borkdude17:03:17

afaik clojure itself doesn't even warn about deprecated vars?

dpsutton18:03:58

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

alexmiller18:03:22

there definitely is a ticket about Clojure :)

borkdude18:03:17

@dpsutton yes, kondo warns, but clojure doesn't

ghadi19:03:11

warns on clojure deprecations or java deprecations or both?

borkdude19:03:30

currently warns on deprecated vars. I just made an issue for deprecated methods/constructors, but it doesn't do that yet

dpsutton19:03:11

i got a bit turned around on which deprecations i was thinking of 🙂

vemv18:03:39

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?

borkdude19:03:39

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

👍 1
dpsutton19:03:16

if you're loading code, does it matter if there are the #= forms? it's executing everything right? you're trusting the source

alexmiller19:03:45

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

alexmiller19:03:54

as dpsutton says, it's not just going to read, it's going to eval as well

vemv20:03:51

@borkdude yeah precisely, it's that difference that I found surprising. TIL about load-string btw!

vemv20:03:34

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

alexmiller20:03:18

that should be the same as using clojure.core/read

alexmiller20:03:51

don't know why you need tools.reader for that

vemv20:03:03

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

dpsutton21:03:59

can i ask what problem you're trying to solve?

vemv21:03:58

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

borkdude21:03:36

Might be something we could add to clj-kondo as well

dpsutton21:03:47

i was just wondering if grasp could identify them

borkdude21:03:48

As in: when you enable the linter, warn

borkdude21:03:35

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

borkdude21:03:26

Or in fact, I do think grasp will throw when it encounters one of those.

borkdude21:03:41

Similar to how bb throws:

$ bb -e '#=(+ 1 2 3)'

----- Context ------------------------------------------------------------------
1: #=(+ 1 2 3)
    ^--- Read-eval not allowed. Use the `:read-eval` option

borkdude21:03:36

You can also parse all your code with edamame (which is one level below grasp / sci)

borkdude21:03:39

to do the same

borkdude21:03:49

it's built on top of tools.reader

dpsutton19:03:47

oh what a weird thing: (var + nonsense) -> #'clojure.core/+

dpsutton19:03:35

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

richiardiandrea23:03:51

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?

richiardiandrea00:03:01

it seems like the instrumentation check my fully qualified key even if not in s/keys

alexmiller00:03:10

The doc string covers this

👍 1