<< Back to previous view

[CLJ-1208] Namespace is not loaded on defrecord class init Created: 03/May/13  Updated: 17/Jun/15

Status: Open
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: Release 1.8

Type: Enhancement Priority: Major
Reporter: Tim McCormack Assignee: Unassigned
Resolution: Unresolved Votes: 5
Labels: compiler, defrecord, deftype

Attachments: Text File 0001-CLJ-1208-load-own-namespace-in-deftype-defrecord-cla.patch     Text File 0001-CLJ-1208-load-own-namespace-in-deftype-defrecord-cla-v2.patch     Text File 0001-CLJ-1208-load-own-namespace-in-deftype-defrecord-cla-v3.patch     Text File 0001-CLJ-1208-load-own-namespace-in-deftype-defrecord-cla-v4.patch     Text File 0001-CLJ-1208-load-own-namespace-in-deftype-defrecord-cla-v5-no-opts.patch     Text File 0001-CLJ-1208-load-own-namespace-in-deftype-defrecord-cla-v5.patch    
Patch: Code and Test
Approval: Vetted


As a user of Clojure interop from Java, I want defrecords (and deftypes?) to load their namespaces upon class initialization so that I can simply construct and use AOT'd record classes without manually requiring their namespaces first.

Calling the defrecord's constructor may or may not result in "Attempting to call unbound fn" exceptions, depending on what code has already been run.

This issue has been raised several times over the years, but I could not find an existing ticket for it:

Approach 1: require the namespace a record/type belongs to during the record/type class init
Patch: 0001-CLJ-1208-load-own-namespace-in-deftype-defrecord-cla-v5-no-opts.patch

Approach 2: like Approach 1 but does the automatic loading only when a :load-ns option is set to true in the deftype/defrecord
Patch: 0001-CLJ-1208-load-own-namespace-in-deftype-defrecord-cla-v5.patch

Note: patch for Approach 1 causes some generative tests to fail since the namespace used to evalaute a defrecord is immediately destroyed thus impossible to load

Comment by Nicola Mometto [ 18/Jan/15 7:10 AM ]

The attached patch approaches this issue by adding a :load-ns options to deftype/defrecord which defaults to false.
When true, the type/record be compiled with a call to clojure.core/require to its originating namespace in its static initializer.

The patch has two known limitations:

  • clojure.core deftypes/defrecords cannot have :load-ns since we use clojure.core/require to load the namespaces so clojure.core needs to be loaded manually anyway
  • clojure.lang.Compiler/demunge is used to get the originating namespace from the deftype/defrecord class name, this means that namespaces like foo_bar are not supported since they get demunged into foo-bar. If this is something that needs to be addressed, it shouldn't be too hard to just pass the unmunged namespace name in the opts map.
Comment by Nicola Mometto [ 22/Jan/15 12:59 PM ]

Updated patch fixing a whitespace error and mentionint :load-ns in the docstrings of deftype/defrecord

Comment by Nicola Mometto [ 11/Mar/15 6:12 AM ]

Updated patch so it applies on lastest HEAD

Comment by Michael Blume [ 17/Jun/15 12:12 PM ]

No longer applies I'm afraid

Comment by Nicola Mometto [ 17/Jun/15 12:22 PM ]

Thanks Michael, updated the patch. I have to say it's getting kind of annoying having to maintain a patch for months without any feedback.

Comment by Alex Miller [ 17/Jun/15 1:03 PM ]

What are the negative impacts if this is always done, rather than being an option?

Comment by Alex Miller [ 17/Jun/15 1:06 PM ]

Also, you should never rely on demunge - it's best-effort for printing purposes only.

Comment by Nicola Mometto [ 17/Jun/15 1:09 PM ]

Does extra bytecode emitted count as a negative impact?

Comment by Alex Miller [ 17/Jun/15 1:15 PM ]

No, I'm not concerned about that.

Comment by Nicola Mometto [ 17/Jun/15 1:48 PM ]

Attached patch that doesn't use demunge but change the macroexpansion of defrecord and deftype to include the namespace segment in the tagsym in deftype* special form

Comment by Nicola Mometto [ 17/Jun/15 2:02 PM ]

Alex, I attached two versions of the last patch, one with :load-ns and one without.
Making :load-ns the default behaviour causes some generative tests to fail since they immediately eliminate the namespace used to defrecord making the record class fail when trying to load said namespace.

I can try to change those tests if necessary.

Generated at Wed Jul 01 22:45:13 CDT 2015 using JIRA 4.4#649-r158309.