Support macros that expand to require forms

Description

Support this kind of code:

(ns foo.bar
(:require-macros [foo.baz :refer [macro-that-expands-to-require]]))
(macro-that-expands-to-require)

Note that we only plan to support this specific case, i.e. it has to come right after the ns form.

This did not work yet because in parse-ns the :ns op did not recur, so we never looked at the second form.

The recur is easy to fix, but after that analyzing the second form (the macro invocation) fails, because the macros are not yet loaded (parse-ns calls analyze but with *load-macros* false).

Environment

None

Attachments

3

Activity

Show:

David NolenJuly 17, 2021 at 4:05 AM

This change was reverted - how to solve this problem is not entirely clear - see and for more context.

`parse-ns` assumes all information can be derived statically from the first form in the file - once macros are allowed many assumptions in the compiler go wrong. So for the time being - the complexity from the proposed change far outweighs the value this feature would have.

Mike FikesMay 30, 2021 at 2:25 PM

See regression CLJS-3311

Arne BrasseurSeptember 12, 2020 at 12:36 PM

I added CLJS-3276-3.patch which adds a test.

Thomas HellerAugust 24, 2020 at 11:59 AM

Back to the other issue of slightly more dynamic require for CLJS. One rather common issue is that some namespaces should only be included in development builds but removed for release builds. One common library that has this issue is the re-frame-10x or the fulcro guardrails. They both add macros that add heavy instrumentation and have a bunch of requires. While the instrumentation can be easily disabled and skipped in the macros the initial require of those namespaces is not so easily removed and bloat the final output quite a bit with unused code which isn’t removable by DCE either.

So the common instructions include swapping out the dependency on the classpath [1] depending on what you are building. In shadow-cljs I added the :ns-aliases option [2] so that you don’t have to mess with the classpath but instead can just replace a single namespace with a stub. Both get the job done of course but I think messing with the classpath is rather unfriendly to the user.

This would be another candidate where having a slightly more dynamic require would be desirable which also cannot strictly be expressed via build tooling alone. You need the actual namespaces to provide to required code, aliased or not. I still think this is better expressed via build config though. Likely that will be used to configure whatever the “dynamic require” is supposed to do anyways, regardless if its a macro so :ns-mod.

 

[1]

[2]

Details

Assignee

Reporter

Patch

Code and Test

Priority

Created August 7, 2020 at 2:48 PM
Updated February 20, 2024 at 7:12 PM