clojure

2026-02-04T08:52:51.215369Z

Is there a way to pretty print EDN with custom tags included, without libraries like fipp? I'm using flatland ordered maps and I want the #ordered/map tags to be included but when I use pprint/pprint it doesn't print the tags

borkdude 2026-02-04T09:10:27.580949Z

maybe print with normal EDN and then re-format it with e.g. cljfmt?

2026-02-04T09:12:07.292079Z

Yeah maybe. I was just wondering if there's anythign built-in.

p-himik 2026-02-04T09:59:59.717619Z

You can certainly use the built-in pprint in a way that prints ordered maps with the printer supplied by the flatland library and prints everything else in a pretty way:

(pp/write {:some {:nested [:map (ordered-map :a 1 :b 2 :c 3)]}}
          :dispatch (fn [obj]
                      (if (instance? flatland.ordered.map.OrderedMap obj)
                        (print-method obj *out*)
                        (pp/simple-dispatch obj))))
Or, if you want to make the change global, just (defmethod pp/simple-dispatch ...). However, if you want to also pretty-print flatland maps, you have to do more work.

šŸ‘ 1
2026-02-04T12:11:47.283719Z

I just realized that I'm not interested in the tags at all šŸ˜„ I just want to get the keys in order and edamame can help with that. My use-case: I have some large JSON files that are annoying to edit. I want to parse the JSON files and convert them to EDN files. Then I'll edit the EDN files and convert them back to JSON and I want to preserve the order all the time. So I can parse JSON with clj-yaml, write it to EDN file with pprint, then I can parse the EDN file with https://github.com/borkdude/edamame?tab=readme-ov-file#preserve-order-of-map-and-set-keys and write back to JSON file.

borkdude 2026-02-04T12:22:07.888309Z

I just commented about that clj-YAML trick in an issue in cheshire. We’re you reading that or sheer coincidence?

2026-02-04T12:37:09.728249Z

sheer coincidence šŸ™‚

Jim Newton 2026-02-04T10:43:33.166019Z

I’m trying to follow the directions of chatgpt, and I supsect it’s leading me in the wrong direction. I would like to use clj from the command line to exec code in a file in the same directory. I have a deps.edn file and a file name dteqt.clj (which contains a ns definition for dteqt) and also contains a definition a function -main. When I call the following command line:

clj -M -cp /Users/jnewton/Documents/courses -m dteqt
I get the error
Execution error (FileNotFoundException) at java.io.FileInputStream/open0 (FileInputStream.java:-2).
-cp (No such file or directory)
has chatgpt lead me astray?

gunnar 2026-02-04T10:54:07.561449Z

man clj give the following:

-Scp CP
              Do NOT compute or cache classpath, use this one instead

Jim Newton 2026-02-04T10:55:50.667879Z

@gunnar, i think i’d like to add . to the class path, not replace the classpath with .

p-himik 2026-02-04T10:56:55.464319Z

But you don't need and should not use a custom CLI-specified classpath if you have deps.edn. That file should already be specifying everything you need. If you clj -h | grep main, you'll see that you can indeed use the -m option to specify the namespace. But the classpath will come from whatever is in deps.edn. If you need a different classpath, just put it under an alias and specify that alias under -M. You can also move the whole -m dteqt thing under that alias, so in the end it can be something like clj -M:dteqt.

p-himik 2026-02-04T10:57:42.093959Z

Check out https://clojure.org/reference/clojure_cli#use_main, especially the last paragraph.

Jim Newton 2026-02-04T10:59:24.769839Z

I don’t really understand. is this correct? the -m says to call -main, right? what does -M do?

p-himik 2026-02-04T10:59:51.602289Z

-M[aliases] Use concatenated aliases to modify classpath or supply main opts

Jim Newton 2026-02-04T11:00:52.371439Z

I saw that, but I don’t know what ā€œconcatenated aliasesā€ are

p-himik 2026-02-04T11:01:01.444499Z

-M allows using aliases from deps.edn. It can be used without aliases at all, in which case it can be omitted. But such usage is considered deprecated so even if you don't need any aliases, -m and some other flags ask you to also use -M for consistency.

p-himik 2026-02-04T11:01:52.687229Z

"Concatenated aliases" are just a string of alias names, concatenated. So if you have aliases :a, :b, and :c, the "concatenated aliases" in this case means :a:b:c.

p-himik 2026-02-04T11:02:35.696119Z

Some examples in the docs are here: https://clojure.org/reference/clojure_cli#options

Jim Newton 2026-02-04T11:02:43.073809Z

ok, what’s an alias?

Jim Newton 2026-02-04T11:03:46.211329Z

for me an alias is a short form of another longer command.

šŸŽÆ 1
āž• 1
p-himik 2026-02-04T11:05:07.227289Z

It's kinda like that, just structured and with abilities to override things: https://clojure.org/reference/clojure_cli#aliases

Jim Newton 2026-02-04T11:06:09.829389Z

so when I take out the -cp foolishness. and I use the command line

clj -M -m dteqt a b c
Here’s the error which chatgpt was trying to fix.
Execution error (FileNotFoundException) at clojure.main/main (main.java:40).
Could not locate dteqt__init.class, dteqt.clj or dteqt.cljc on classpath.

Full report at:
/var/folders/c1/sqxjhjm15gdcyr49z7r4k1mr0000gn/T/clojure-1362372849798786874.edn
make: *** [all] Error 1

p-himik 2026-02-04T11:15:29.847219Z

For the vast majority of cases, deps.edn and clj are enough, when used properly. Most of the time, there's no need for make or shell scripts, precisely because of aliases. >

Could not locate dteqt__init.class, dteqt.clj or dteqt.cljc on classpath.
> 
This is pretty self-explanatory. If you have dteqt.clj or something else mentioned in the error, it's not on the classpath. If you put it in ., I'd definitely suggest moving it under some nested directory and adding that to deps.edn under the :paths key (by default it's ["src" "classes"], IIRC).

p-himik 2026-02-04T11:24:22.445079Z

And if you still want for it to be in ., just specify :extra-paths ["."] under some alias. Or :replace-paths (same as just :paths).

Jim Newton 2026-02-04T12:49:47.981519Z

if I remove the -main function and just top-level its content, then I can run the script as follows.

clj -Sdeps '{:deps {org.clojure/clojure {:mvn/version "1.11.1"}  org.clojure/data.json {:mvn/version "2.4.0"}}}' -M dteqt.clj
However, it doesn’t seem to work with any of the advice from above nor from chatgpt. I think there’s something subtle wrong. but at least I can proceed with this ugly workaround … it is being called from a Makefile anyway.

p-himik 2026-02-04T12:53:54.525229Z

But what doesn't work? What are the symptoms?

Jim Newton 2026-02-04T12:57:35.930939Z

My workaround is just to put a top-level call

(apply -main *command-line-args*)
in the file, and then call as I’ve mentioned above. However, every attempt to use the -m flag gives me the familiar error. despite efforts to add :extra-paths. maybe its my java version or something bizzzzare like that.
Execution error (FileNotFoundException) at clojure.main/main (main.java:40).
Could not locate dteqt__init.class, dteqt.clj or dteqt.cljc on classpath.

p-himik 2026-02-04T13:00:47.712599Z

Should be nothing bizarre. What's in your deps.edn (the relevant parts, at least) and how exactly do you try to run the function from the CLI when it fails with that message?

Jim Newton 2026-02-04T13:02:28.479769Z

Here is the content of the deps.edn file.

{:deps {org.clojure/clojure {:mvn/version "1.11.1"}
        org.clojure/data.json {:mvn/version "2.4.0"}}
 }

Jim Newton 2026-02-04T13:03:07.550969Z

I tried to add the extra paths like this

{:deps {org.clojure/clojure {:mvn/version "1.11.1"}
        org.clojure/data.json {:mvn/version "2.4.0"}}
 :extra-paths ["."]
 }

p-himik 2026-02-04T13:03:34.958359Z

:extra-paths is only for aliases, not for the top-level...

p-himik 2026-02-04T13:05:20.113429Z

$ mkdir clj-cli-test
$ cd clj-cli-test
$ echo '{:aliases {:dteqt {:extra-paths ["."] :main-opts ["-m" "dteqt"]}}}' > deps.edn
$ echo '(ns dteqt) (defn -main [& args] (println "main called with" args))' > dteqt.clj
$ clj -M:dteqt
main called with nil
$ clj -M:dteqt hello there
main called with (hello there)

2026-02-04T14:46:43.321899Z

I think that this thread has shown that the advice you've gotten from chatgpt has been unhelpful at many different points. I do not recommend using the tool for learning new things, as it often makes small errors that can hinder understanding. Generally, chatgpt is more useful on subjects that you already know well because you can spot the errors. Instead, I recommend looking through the guides on http://clojure.org, and asking questions here or in #beginners

Jim Newton 2026-02-04T14:57:39.749409Z

@suskeyhose i didn’t imagine that calling a script from the command-line should be so fraught with pitfalls.

p-himik 2026-02-04T14:58:56.631459Z

It shouldn't be, and it isn't really. ChatGPT simply shits the bed inexcusably here, for some reason.

Jim Newton 2026-02-04T15:00:35.456259Z

as an aside. I am somewhat dyslexic … i’m pretty sure that at some point i probably typed detqt rather than dteqt. apparently if you give clj an alias that does not exist, it silently ignores and does something different. for example. clj -M:detqt seems to go into interactive clojure repl. while clj -Mdteqt does what I want.

p-himik 2026-02-04T15:03:02.229809Z

Note that : should still be there, so it should be -M:dteqt. Regarding a missing alias - no idea why it was done that way, perhaps it's just the default behavior of how maps work when you look up a key that doesn't exist. No error is thrown. But maybe there's a deeper meaning and a deliberate decision behind not throwing anything.

2026-02-04T20:52:29.061499Z

It possible your issue is because classpath are really gnarly. You have to explicitly have a path to all subdirectory or there are some weird glob patterns you can use when you manually provide it using the command argument.