This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-12-25
Channels
- # adventofcode (16)
- # babashka (8)
- # beginners (13)
- # calva (22)
- # clj-on-windows (20)
- # clojure (49)
- # clojure-australia (1)
- # clojure-europe (6)
- # clojure-nl (2)
- # clojure-uk (3)
- # clojurescript (4)
- # emacs (1)
- # fulcro (20)
- # introduce-yourself (2)
- # java (2)
- # missionary (2)
- # off-topic (10)
- # other-languages (2)
- # pathom (4)
- # re-frame (15)
Q: When I'm requiring the ns, the Clojure runtime will load all the functions from that namespace, right?
Yes, unless a function definition is wrapped in a conditional, or somehow excluded otherwise:
(when false
(defn ...))
Right! Thanks!
user=> {:a.b.c/a :a.b.c/b}
#:a.b.c{:a :a.b.c/b}
user=> (pr-str {:a.b.c/a :a.b.c/b})
"#:a.b.c{:a :a.b.c/b}"
Should I or should I not add support for this to an EDN parser?I am not an author of the EDN specification, so have no authority in this matter. I can say some things that are perhaps already obvious to you, so maybe unhelpful, but nevertheless true. The short-hand of putting a namespace before the {
character of a map whose keys are all namespace-qualified, and all have the same namespace qualifier, was introduced after the EDN specification was written, and a reading of https://github.com/edn-format/edn does not mention or even imply (to my reading) that this is part of EDN. This suggests that an EDN parser should not support it.
On the other hand, what one might consider a reference implementation does support it:
=> (clojure.edn/read-string "#:a.b.c{:a :a.b.c/b}")
#:a.b.c{:a :a.b.c/b}
I think some more statements that are true are that despite some people wanting the EDN spec to nail down all of these details, the EDN authors seem unlikely to be willing to change the EDN spec to do so. Could that change in the future? Sure, if the authors decide to. It hasn't happened in the 8 years since it was published, though, so seems unlikely to any time soon.
There are some similarities here with some people wishing that there were a very precisely written specification for Clojure the programming language. That is a much more complex task than a tightly specified syntax for a data interchange format, so these are not identical situations, just similar.
my current thought is that #:a.b.c{:a :a.b.c/b}
is invalid edn, which means if i added support i would be supporting a superset of edn
Can you split the implementation between a lean core which implements only the specification and additional features?
i see no reason why i can’t. The code for that is here. I just need to flag what happens if i find a keyword after the #
published with the option enabled by default https://crates.io/crates/edn-format
philosophical / stylistic question, how do you choose the root namespace layout for your project?
I see plenty of options around
• java like, com.group.project.namespace
• user-prefix user.tool
• intent / semantic prefix next.jdbc
• old-school: myproj.core
Would appreciate some pros/cons and your general thoughts
If you are writing a lib, you will be mixing with other libs and should maintain a globally unique space that you control to some degree, either by (reverse) dns, or by trademark, or by conveyed identity by a third party, like github
Generally that's probably similar to your group id in maven coord
If you're writing an app and not publishing it for others to use, do whatever you want (as long as it's unlikely to collide with the lib approach above)
So the schema for cognitect.aws.client.api
could be thought of as user.domain.functionality.api
?
Sure although domain and functionality are pretty vague and totally up to you
It needs to be sufficiently unique for the user/org
So the creative project names handle it by way of just being cool (promesa, jsonista, etc)
-> unless I come up with a cool project name, I should probably prefix with my user/org
At this point, even if you come up with a "cool project name", I think a user/org prefix is a good idea. I don't think it necessarily needs to be full reverse DNS (unless your user/org prefix is pretty generic already).
I agonized over next.jdbc
vs seancorfield.jdbc
or seancorfield.next.jdbc
for quite a while, and polled the potential users before I decided to go with just next.jdbc
.
The reason we have so many myproj.core
namespaces is that lein
never required qualified or multisegment project names and then just slapped .core
on the end of any single-segment names.
That's why clj-new
requires either user/project
or user.project
so it can have a qualified main ns without .core
. Some folks have complained and I've just expanded the explanation of why it does this 🙂
Because the answer is "it depends"? 😁
Just my 2 cents. I like it when the main api ns is just the name of the lib (with whatever prefix options you have available). nippy
-> taoensso.nippy
, uri
-> lambdaisland.uri
, etc... If then the prefix also matches also the artifact. Perfect.
If you are going to publish a library on Clojars, I think you should go with what you call java style.
From April this year Clojars started https://github.com/clojars/clojars-web/wiki/Verified-Group-Names. That does not mandate any particular layout for the namespace, but I rather strongly think they should match.
E.g. on the following projected hosted at https://github.com/ivarref/yoltq I'm using com.github.ivarref
as namespace root, and com.github.ivarref
as the (verified) group id.
What are actual benefits of binding Clojure vars in static fields, is it for the performance optimization on the Compiler level? See https://gist.github.com/FieryCod/ab335ff24a0bc1bedef8e0591351ae40
I think the another feature of this is the GraalVM can cleanly track not used classes (not used Clojure functions) and remove them since each one is bound to a static var. cc @U04V15CAJ.
@U064X3EF3 Could you elaborate?
If it's a static field you load it once vs loading it every time you invoke
Got it. It's a performance optimization then. Trading the startup time for maximum performance, right?
I’m not sure that framing is quite accurate. It depends on what you choose to call “startup.” If that class is never loaded, it does not contribute to startup time at all. If that class is loaded and has its method invoked, then then net time added is zero. The only time you incur additional overhead is if you, for some reason, load the class, but never use it.
But all the classes (compiled functions) are loaded via the __init
class when (:require [clojure-string])
is used in this case. Which means that the initialization of each instance in static slows the startup time compared to the hypothetical situation when the function implementation would be instantiated on the actual call of a function.
You can use only one function from clojure.core
and your startup time is a sum of instancing each var in the namespace during the implicit load.
Yeah those fall into the latter category I mentioned. It’s fair to point out that clojure.core
is particularly affected by this behavior.
It's only about clojure.core
. When using any clojure
library rarely one uses the 100% of it's functions.
There is an old branch for lazy var loading that avoids this cost, maybe will eventually be revived. At the time it had the downside of making regular invocation a bit slower due to the load check. There are better jvm tools available now that could mitigate this.
What tools do you have in mind?