clojure-dev

Issues: https://clojure.atlassian.net/browse/CLJ | Guide: https://insideclojure.org/2015/05/01/contributing-clojure/
nathanmarz 2019-07-31T19:14:52.081600Z

is this intended behavior by Clojure? https://gist.github.com/nathanmarz/6c3461fd9f45e28248ace85eaee5a4f5

2019-07-31T20:12:21.086900Z

There are only a few people who can answer that question as you asked it, and I am not one of them, unfortunately. You probably already know that it is intended behavior to munge dash characters in namespace symbols into underscores before looking for resources/files on the classpath, because the JVM does not support dashes. Given that, it seems that there might be unavoidable naming issues in this area, like what you have found? I haven't thought deeply about it, but perhaps such issues would be avoidable if *loaded-libs* only contained the post-munged names, but that sounds likely to cause upset for any Clojure tooling that peeks inside *loaded-libs*.

nathanmarz 2019-07-31T20:24:57.087500Z

the context is we had a bug caused by unexpected redefinitions from a typo in a require for a namespace containing a -

2019-07-31T20:35:44.089Z

I don't know the history here, but it surprises me a little that you can even successfully do a require using test_ns, when the ns form inside the file is test-ns. It seems reasonable that such a require should fail.

2019-07-31T20:36:40.089700Z

you'd imagine that it loads the file and then errors because test_ns hasn't been defined as a namespace?

2019-07-31T20:36:50.090Z

that seems like a reasonable expectation to me

2019-07-31T20:38:52.090800Z

Although my quick REPL testing is not matching my memory of code that I thought was present that checks whether the namespace exists near the end of the require. Double-checking to see where my memory is going wrong here.

nathanmarz 2019-07-31T20:41:40.091500Z

yea, that does seem like better behavior

nathanmarz 2019-07-31T20:42:03.092Z

which in our case would have caught the typo immediately rather than cause a very difficult debugging session

2019-07-31T20:44:02.093Z

Ah, if you do require of test_ns with an :as clause, and the file has ns for test-ns, then you get an error. Without the :as, it does not.

2019-07-31T20:45:45.093400Z

The error checking is also enabled via use, but understood if you wouldn't want to go there.

2019-07-31T20:47:12.094200Z

when you read a lot of this code you start wondering whether the term lib was (or still is?) used to mean something slightly different from either "namespace" or "source file"

2019-07-31T20:47:33.094600Z

I think I mentioned that here once a year ago but can't remember if anybody said anything useful about that

2019-07-31T20:47:49.095Z

but I could imagine that being a barrier to assuming that the arg to require is a namespace symbol

2019-07-31T20:49:27.095900Z

from the require (which describes its args as libs, not namespaces) docstring:

A 'lib' is a named set of resources in classpath whose contents define a
  library of Clojure code. Lib names are symbols and each lib is associated
  with a Clojure namespace and a Java package that share its name. A lib's
  name also locates its root directory within classpath using Java's
  package name to classpath-relative path mapping. All resources in a lib
  should be contained in the directory structure under its root directory.
  All definitions a lib makes should be in its associated namespace.

2019-07-31T22:13:36.096400Z

I do not recall whether linters like Eastwood or clj-kondo would catch that kind of thing.

borkdude 2019-07-31T22:18:14.097100Z

summarized: the check should be: if there is an ns foo-bar, but you require with foo_bar, it should give a warning?

borkdude 2019-07-31T22:19:42.097600Z

or give a warning when you're using underscores at all?

2019-07-31T22:20:50.098300Z

I would think the most accurate check would be: the symbol naming the namespace in a require/use, and the ns form name symbol, should be equal.

borkdude 2019-07-31T22:21:53.099200Z

but what happens if foo_bar and foo-bar both exist?

2019-07-31T22:22:09.099600Z

Eastwood definitely has checks already for compatibility between ns form symbols and the file name it is inside of on the file system.

2019-07-31T22:22:56.100500Z

Both namespace symbols? They can't be both used in a single ns form, of course. And for require to work, they would both have to be in the same file.

2019-07-31T22:23:17.101Z

Two ns forms in the same file is not illegal, but pretty strange in most code.

borkdude 2019-07-31T22:24:05.101800Z

right and require is file based and files must always have namespaces

borkdude 2019-07-31T22:24:56.103300Z

so you could have either foo_bar with (ns foo-bar ..) or (ns foo_bar), so a check would have to know about that and then emit a warning. that's something clj-kondo could easily do.

2019-07-31T22:24:57.103500Z

Well, require with :as, or use, both give an error if loading the file it finds does not end up causing the target namespace to exist.

2019-07-31T22:25:53.104400Z

A file foo_bar with either of those ns forms are legal, and would work if you did a require + :as with a matching symbol to name the namespace.

borkdude 2019-07-31T22:26:23.105200Z

this is a very rare case I would say. stylistically, I'd say: avoid underscores in namespaces names

2019-07-31T22:26:39.105600Z

The warning that would have saved time in the scenario above cannot be caught by looking at the contents of only one file, but across files.

2019-07-31T22:27:22.106700Z

Stylistically forbidding underscores in namespace names could be adopted as a project convention, of course.

borkdude 2019-07-31T22:28:22.107200Z

this kind of check would probably be just a few lines of scripting using the data that clj-kondo spits out: https://github.com/borkdude/clj-kondo/tree/master/analysis#data

2019-07-31T22:29:52.107700Z

Project style/convention-wise, mandating :as for all requires would also prevent this.

2019-07-31T22:30:09.108200Z

or rather, catch it quickly.

borkdude 2019-07-31T22:30:11.108400Z

mandating :as for all requires is not something I would agree with

borkdude 2019-07-31T22:30:37.108600Z

there are good reasons to not have an alias

alexmiller 2019-07-31T22:34:43.110200Z

Why?

seancorfield 2019-07-31T22:35:26.111200Z

I agree. We have a number of namespaces where :require ... :refer [...] is the appropriate usage (because they declare operator-like symbols and using an alias makes them harder to read).

borkdude 2019-07-31T22:35:45.111300Z

I mean, you cannot require a namespace which is not in a file, but defined in the REPL

2019-07-31T22:36:34.112400Z

There is of course the possibility of monkey-patching require in your local dev environment to do the strong checking even without :as. Just blue-skying here, at this point, I know.

borkdude 2019-07-31T22:38:25.112800Z

oh you can.

borkdude 2019-07-31T22:39:33.113Z

I think I was confused by how it works in CLJS