clojure-dev

Kirill Chernyshov 2025-11-20T14:22:44.723259Z

Not sure if this is a bug or feature but clojure.edn violates EDN format specification:

user=> (clojure.edn/read-string {:readers {'foo (fn [val] (prn "!!!") val)}} "#_ #foo [1 2 3]")
"!!!"
Execution error at user/eval176 (REPL:1).
EOF while reading
There are two problems: 1. The custom reader function is called even when inside a discard 2. I did not expect an EOF error in this case

2025-12-01T15:55:50.469809Z

i updated the patch today to cover discarded aliased keywords and aliased keywords in skipped reader conditional branches

2025-11-25T21:23:20.137459Z

i expanded the https://clojure.atlassian.net/browse/CLJ-2928 and attached a patch

ghadi 2025-11-20T14:25:28.027999Z

discard impl does an ordinary read, then throws away the result

ghadi 2025-11-20T14:25:53.788619Z

two consequences to this: reading tagged forms invokes their handlers, and aliases are resolved

ghadi 2025-11-20T14:26:22.698079Z

e.g. not being able to discard an invalid/keyword

ghadi 2025-11-20T14:26:53.180029Z

there are JIRA(s?) about this

ghadi 2025-11-20T14:27:11.163829Z

2. #_ discards the next form, which is a tagged vec

ghadi 2025-11-20T14:27:22.862979Z

the tag is not a separate form

ghadi 2025-11-20T14:27:42.780749Z

there is nothing after the tagged vec to read

borkdude 2025-11-20T14:28:41.170929Z

This feels a bit inconsistent though:

user=> (clojure.edn/read-string "#_1")
nil
user=> (clojure.edn/read-string {} "#_1")
Execution error at user/eval170 (REPL:1).
EOF while reading

Kirill Chernyshov 2025-11-20T14:28:47.444449Z

user=> (clojure.edn/read-string "#_ #inst \"2027-06-06\"")
nil

Kirill Chernyshov 2025-11-20T14:30:37.327239Z

also I can't see a connection between alias resolution and invocation of custom reader fn

ghadi 2025-11-20T14:30:59.203719Z

yes that violates my expectations. all should eof

borkdude 2025-11-20T14:32:24.256609Z

docstring says: > Reads one object from the string s. Returns nil when s is nil or empty

ghadi 2025-11-20T14:32:25.418739Z

alias resolution and tag handler fns are both examples of things not needing to happen when discarding

ghadi 2025-11-20T14:32:37.394529Z

oh -- then no. all should do that

ghadi 2025-11-20T14:32:55.102759Z

didn't realize that read-string promised that!

borkdude 2025-11-20T14:33:33.377249Z

here it passes explicitly nil, but when not providing eof explicitly it doesn't default to nil:

([s] (read-string {:eof nil} s))
  ([opts s] (when s (clojure.lang.EdnReader/readString s opts))))

ghadi 2025-11-20T14:33:35.370779Z

(I almost never use read-string, and made an incorrect assumption, editing my messages above)

Alex Miller (Clojure team) 2025-11-20T14:41:04.030969Z

Unsure if questions still open here…

borkdude 2025-11-20T14:42:00.349209Z

Not sure what you mean by opening questions, but either the docstring has to change or the impl I guess?

borkdude 2025-11-20T14:42:14.166819Z

and since the latter would be breaking, probably changing the docstring is safest

2025-11-20T14:43:22.542909Z

is changing a throw to not throw a breaking change?

borkdude 2025-11-20T14:44:25.430169Z

I'd say so

borkdude 2025-11-20T14:44:55.157699Z

I mean, depends on the context, but here it's a default option to throw on EOF

👍 1
borkdude 2025-11-20T14:45:26.588849Z

people might have try/catch-ed this - changing it to return nil would break them

Kirill Chernyshov 2025-11-20T14:46:34.354049Z

> Unsure if questions still open here… and what about calling reader fns inside discard?

Alex Miller (Clojure team) 2025-11-20T14:47:59.847219Z

What about it?

Alex Miller (Clojure team) 2025-11-20T14:48:42.546749Z

Discard reads, then discards

Kirill Chernyshov 2025-11-20T14:49:28.354699Z

https://github.com/edn-format/edn?tab=readme-ov-file#discard according to spec it is an error if user supplied reader function is called inside discard

borkdude 2025-11-20T14:50:14.626549Z

> A reader should not call user-supplied tag handlers during the processing of the element to be discarded. That's interesting

Alex Miller (Clojure team) 2025-11-20T14:50:42.133499Z

Is this a question about clojure.edn readers or clojure.core

Kirill Chernyshov 2025-11-20T14:50:53.752869Z

clojure.edn

Alex Miller (Clojure team) 2025-11-20T14:51:49.143759Z

It sounds like there are maybe two questions here. It would be helpful to fully restate those two questions, perhaps in ask Clojure questions

Kirill Chernyshov 2025-11-20T14:52:19.585239Z

sure

borkdude 2025-11-20T14:59:00.458269Z

despite from this being different from the docs, I wonder why this is important to you - are you increasing a counter while the tag function is executed or so?

2025-11-20T15:00:50.481709Z

bugs are bugs and worth fixing

Kirill Chernyshov 2025-11-20T15:01:45.859679Z

I work on C implementation for EDN parser where primary goal is to pedantically follow edn-format/edn specification by default (optionally extend to clojure.edn capabilities) I found this specific line interesting and tried behaviour of fast-edn.core first (reported as a bug), then later I discover that clojure.edn is doing the same thing

borkdude 2025-11-20T15:02:07.903309Z

I'm not saying it shouldn't be aligned with the docs. But learning why this bugs someone is worth informing other things

👍 1
borkdude 2025-11-20T15:03:27.472839Z

(FWIW, edamame also just calls reader functions while in discard mode)

borkdude 2025-11-20T15:03:54.925679Z

(edamame is EDN by default, but can be tuned up to full clojure, so it's a grey area)