-
Notifications
You must be signed in to change notification settings - Fork 177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Exponential increase in generated code when there are multiple nested hiccup2.core/html calls #210
Comments
Macros are evaluated from the outside in, so we could certainly look through the syntax tree and do something to reduce the nesting. There may also be a better solution to the problem, but keeping the API backward compatible ties our hands somewhat. |
If Alternatively, create a new internal function similar to |
Wouldn't it be helpful to be able to optionally disable all the preprocessing at compile time and do everything at runtime? Then the evaluation happens inside-out, and everything becomes easier. If someone has code like in this issue, he may not want an optimisation at compile time. |
I think ideally I want to separate out compilation entirely, but that will require some consideration and probably a |
I came up with an idea for solving this issue by decomplecting the Hiccup API: Instead of
In application code, typically each template will always be used to produce the same output format. So we don't need the ability to switch between different output formats. You might have some SVG XML inside an HTML component, but that's about it. To support code completion, the variants which don't escape strings are prefix with "unsafe-"; this way they will not be shown in code completion after the user has typed the first character. In library code it may make sense to support different output formats, so component libraries can continue using For backward compatibility,
|
I found an easy solution for that problem. Just move a let around your hiccup vector. Then Hiccup cannot do any compile-time optimisations. |
In your case you don't even need the let. Just hiccup everything at the end.
I don't know if this answers the problem. In all my cases where I had a big macro expansion I was able to fix it. In my opinion using |
Why: - Hiccup generates 8 code paths every time the hiccup2.core/html macro is used, one for each combination of the output formats (html, xhtml, xml, sgml) and string escape mode (true, false). In practice, an application uses only one or two of them, and the rest is dead code. - This fixes the problem of exponential amount of generated code in some situations. See weavejester/hiccup#210
Why: - Hiccup generates 8 code paths every time the hiccup2.core/html macro is used, one for each combination of the output formats (html, xhtml, xml, sgml) and string escape mode (true, false). In practice, an application uses only one or two of them, and the rest is dead code. - This fixes the problem of exponential amount of generated code in some situations. See weavejester/hiccup#210
This is similar to #205 but less common. Consider the following code:
In the generated code, foo will appear 8 times, bar 64 times, and gazonk 512 times.
If you try to evaluate this code normally (i.e. without macroexpand-all), it will throw "IndexOutOfBoundsException: Method code too large!"
Each level of nesting multiplies the code by 8, because every
h/html
checkshiccup.util/*html-mode*
andhiccup.util/*escape-strings?*
again and generates the 8 code paths.Is there a way for a Clojure macro to recognize that it's nested within itself? Then those 8 code paths could be generated at only the outermost
h/html
, and the inner macros could use the same html and escape mode as the outermost macro.Hiccup version 2.0.0-RC3
Workaround
Extract the inner
html
macro call to a function, so that you won't have many nestedhtml
macros.The text was updated successfully, but these errors were encountered: