LaTeX on this site supports \newcommand
and \renewcommand
. This is very nice, but I noticed that the scope of these definitions is the entire rest of the page. That's consistent with how LaTeX behaves, but it could be undesirable on this site where the page contains posts by different people: one person's \newcommand
affects everyone who posts below them.
To illustrate the problem, in this question I am including
\renewcommand{\sin}{\cos}
$\renewcommand{\sin}{\cos}$Now anyone who uses \sin
in an answer or a comment will get $\cos$ instead.
(I considered exploiting this when asking some simple trig question on main and then watching the confusion, but decided not to be evil.)
It would be good if the scope of \newcommand
and friends could be limited to the current question/answer/comment, but I don't know whether this is possible.
5 Answers 5
It pains me to break this thread by fixing the issue, but here we are. :)
We are now inserting \begingroup
and \endgroup
directives into post and comment bodies, so all command definitions should be scoped to individual posts.
For now, I'm only enabling this on Math (and here on meta), but barring any issues this change will go live on all MathJax-enabled sites next week.
-
3$\begingroup$ It seems that the issue isn't completely fixed. See math.meta.stackexchange.com/q/29702/18398 $\endgroup$JRN– JRN2019年01月28日 04:25:16 +00:00Commented Jan 28, 2019 at 4:25
-
8$\begingroup$ To add a bit more to detail to @Joel's comment: a newcommand in titles can still cause issues. This is especially a problem when a title containing a newcommand appears in "linked" and "related." This can create rather confusing situations. $\endgroup$2019年01月28日 08:11:55 +00:00Commented Jan 28, 2019 at 8:11
-
4$\begingroup$ It's still broken if you do $\endgroup \renewcommand{\sin}{\cos} \begingroup$ \endgroup \renewcommand{\sin}{\cos} \begingroup. As you can see, it broke the post below. $\endgroup$qbt937– qbt9372019年02月10日 20:35:55 +00:00Commented Feb 10, 2019 at 20:35
-
4$\begingroup$ @qbt937 Yeah... Although honestly, that isn't something that would come up naturally. The only way this'd happen is from someone trying to mess with the page and I'm okay with leaving that up to being edited out and the user potentially being suspended if they keep at it. $\endgroup$2019年02月11日 17:46:43 +00:00Commented Feb 11, 2019 at 17:46
-
1$\begingroup$ Thanks for making the change. How are you faring with this, is anything rolled out over the other sites already? Or are there still issues to be fixed / high prio tasks taking precedence? Cheers, Maarten, mod at cryptography. Or should we create a feature request to obtain it? $\endgroup$Maarten Bodewes– Maarten Bodewes2019年03月05日 13:34:24 +00:00Commented Mar 5, 2019 at 13:34
-
5$\begingroup$ @MaartenBodewes It's live on every SE site that has Mathjax enabled. You don't need to do anything special. $\endgroup$2019年03月05日 16:31:11 +00:00Commented Mar 5, 2019 at 16:31
-
2$\begingroup$ Of course, now some of comments and answers are not rendered correctly - if the OP used macro defined in the question. (And, of course, at that time they were rendered fine.) But probably there is not too many of them and some of them might eventually get edited. More on this in chat and in A recent post by quid is somewhat related. And there was a short discussion on MathOveverflow Meta. $\endgroup$Martin Sleziak– Martin Sleziak2019年04月12日 10:39:28 +00:00Commented Apr 12, 2019 at 10:39
-
1$\begingroup$ @AdamLear I have posted a follow-up question concerning macros in titles - asking both whether titles should be inside begingroup...endgroup too and to which extent defining macros in the titles should be discouraged. $\endgroup$Martin Sleziak– Martin Sleziak2019年06月18日 07:30:27 +00:00Commented Jun 18, 2019 at 7:30
As Mariano points out, this has been reported before. Because of that conversation, MathJax v2.0 includes an extension (the begingroup extension) that would allow you to isolate the effects of \def
, \newcommand
, etc. to a single question, answer, or comment, but it would require changes to the SE code to force that to be used.
The changes would be to include begingroup.js
in the TeX extensions array for the site's configuration, and outputing a $\begingroup$
at the beginning of each questions/answer/comment and an $\endgroup$
at the end. (These might want to be enclosed in a hidden <div>
or some other tag so that they don't introduce any unwanted space.) The preview code would also have to be modified to include these, but that would need to be a bit more sophisticated, since the typesetting can be canceled in the middle (by new characters being typed) so the final \endgroup
would need to be handled separately in that case. I would be happy to work that out if the powers-that-be wanted to coordinate efforts on that.
Edit: Asaf asks whether you can do anything like this "by hand". I had considered telling you about the \require{}
command that will load extensions that haven't been included in the configuration, but I didn't. That's because the current preview code will not work well with the begingroup
extension. If you include a $\begingroup$
in your post, but haven't yet typed the $\endgroup$
, then each character you type will cause the post to be reprocessed, and each reprocessing will cause a new \begingroup
to be performed without a corresponding \endgroup
. This will use up memory that will not be freed (until you go to another page), and can slow MathJax down.
Similarly, if you have a long post, then even if you do have matching \begingroup
and \endgroup
tags, if you type fast, each letter will cancel MathJax in the middle of what it is doing, and so MathJax may be canceled after processing the \begingroup
but before the \endgroup
. Again, you can use up memory.
This is what I meant when I said that the preview code would need to be modified to take that into account.
While it is technically possible to use the begingroup
extension by hand, you would have to be careful about how you do it. On the plus side, it only affects you when you are editing (or someone else who is editing your work), so perhaps you would be willing to put up with the difficulties.
In any case, your example doesn't really show how it would work, since \begingroup
and \endgroup
don't protect you from definitions from outside your answer; they protect others from definitions in your answer. So to see it really work, you would need to use something like
$$
\require{begingroup}
\begingroup
\renewcommand{\tan}{\operatorname{grey}}
\tan\theta
\endgroup
\ne
\tan\phi
$$
to get
$$ \require{begingroup} \begingroup \renewcommand{\tan}{\operatorname{grey}} \tan\theta \endgroup \ne \tan\phi $$
This works, but if you don't get the balancing of begin and end groups properly during the editing process, you can be left with a lot of open begin groups, that contain local definitions that don't go away (until you reload the page).
-
1$\begingroup$ Is this workaround applicable "by hand"? (Testing: $\begingroup\sin\neq\cos\endgroup$) $\endgroup$2012年05月05日 20:53:14 +00:00Commented May 5, 2012 at 20:53
-
$\begingroup$ @AsafKaragila I added material to my original answer about that. $\endgroup$Davide Cervone– Davide Cervone2012年05月06日 10:31:25 +00:00Commented May 6, 2012 at 10:31
-
$\begingroup$ Yes, I saw. Thank you. Do note that the main problem which Nate pointed is that vandals can post a malicious code and "ruin" the answer. $\endgroup$2012年05月06日 10:40:58 +00:00Commented May 6, 2012 at 10:40
-
$\begingroup$ Yes, I understand that. That is why I said it would take changes to the SE code to do this properly. I thought you were asking about using \begingroup and \endroup yourself (to isolate your local macros so they don't interfere with others). Perhaps I misunderstood. I do not see a way to prevent others from making definitions without changes to SE code. $\endgroup$Davide Cervone– Davide Cervone2012年05月06日 11:46:55 +00:00Commented May 6, 2012 at 11:46
-
$\begingroup$ I was hoping that there would be a way to locally reset inside an answer. $\endgroup$2012年05月06日 11:50:44 +00:00Commented May 6, 2012 at 11:50
-
2$\begingroup$ I suppose if the questioner added
$\require{begingroup}\begingroup$
at the bottom of the question, you could use$\endgroup\begingroup$
at the top and bottom of your answer or isolate your response from the effects of others (and localize your changes to your answer as well). But this takes cooperation of the questioner, and it also has all the preview problems that I mentioned. $\endgroup$Davide Cervone– Davide Cervone2012年05月06日 11:50:55 +00:00Commented May 6, 2012 at 11:50 -
$\begingroup$ That is effectively what I am suggesting that the SE code does between each question/answer/comment, but you could do it by hand for your answer provided there was an initial \begingroup in the question. $\endgroup$Davide Cervone– Davide Cervone2012年05月06日 11:54:22 +00:00Commented May 6, 2012 at 11:54
-
$\begingroup$ Of course that would still only prevent accidental macro leaking, not malicious leaking. For one, the begingroup extension also provides
\gdef
, which works around\begingroup
/endgroup
. Moreover, even without\gdef
, a malicious poster could simply use\endgroup\renewcommand{\sin}{\cos}\begingroup
to make his definition intentionally leaking. So if the goal is to prevent malicious behaviour, it has to use a mechanism which isn't accessible to users. $\endgroup$celtschk– celtschk2012年07月13日 07:10:33 +00:00Commented Jul 13, 2012 at 7:10 -
$\begingroup$ Your point is well taken, but I think it could be handled as follows: make a new macro
\reset
that does the action of\endgroup\begingroup
(easily done), and remove the\begingroup
,\endgroup
,\gdef
, and\global
macros. Use$\reset$
between questions/answers/posts, and rather than call MathJax's typeset by itself, first queue the\begingroup
function directly, then the typeset then the\endgroup
function. While the user could still call\reset
in her message, it would not provide a means of entering global definitions. $\endgroup$Davide Cervone– Davide Cervone2012年07月13日 10:38:59 +00:00Commented Jul 13, 2012 at 10:38 -
$\begingroup$ @DavideCervone: If you make
\reset
completely reset the MathJax engine (i.e. remove even macros defined globally), there's no need to remove the macros from the begingroup extension. But you're right,\reset
being available to users would not be harmful. $\endgroup$celtschk– celtschk2012年07月14日 10:25:54 +00:00Commented Jul 14, 2012 at 10:25 -
$\begingroup$ @Davide: I added a fix for this issue into SOUP, but it's kind of crude: I'm basically just injecting the equivalent of
$\endgroup$ $\begingroup$
at the beginning of each post and comment. It's working, but if you'd have any suggestions on how to do it more cleanly / elegantly, please do tell. The current code I have is here (look formathJaxSetup
). $\endgroup$Ilmari Karonen– Ilmari Karonen2014年01月15日 21:15:32 +00:00Commented Jan 15, 2014 at 21:15 -
$\begingroup$ @IlmariKaronen, what you have looks good except for two things: (1) you don't need to have two separate expressions, you could just do
$\endroup\begingroup$
, and (2), it is possible for a user to redefine\endgroup
or\begingroup
within their post. Preventing that would require overriding part of MathJax's code for defining macros (but it could be done). Also, make sure you first post only starts with$\begingroup$
with no leading\endgroup
, and your last one should only have$\endgroup$
. $\endgroup$Davide Cervone– Davide Cervone2014年01月16日 16:05:47 +00:00Commented Jan 16, 2014 at 16:05 -
$\begingroup$ @DavideCervone: The reason I'm using two separate expressions is precisely so that if
\endgroup
fails (because the stack is already empty), the following\begingroup
will still run. While I could omit the first\endgroup
and the last\begingroup
on the page as you suggest, having new posts or other content loaded via AJAX could still cause subsequent typeset passes to start with an unbalanced\endgroup
, so I have to tolerate that possibility. What I'd really like to do is implement your / celtschk's\reset
idea above, but I don't know enough about MathJax internals to see how. $\endgroup$Ilmari Karonen– Ilmari Karonen2014年01月16日 19:50:36 +00:00Commented Jan 16, 2014 at 19:50 -
1$\begingroup$ @DavideCervone: OK, I did figure out how to do it by monkey-patching parts of the begingroup extension. It's a bit complicated, and likely to break if the extension ever gets rewritten, but otherwise it works very nicely. $\endgroup$Ilmari Karonen– Ilmari Karonen2014年01月16日 22:50:01 +00:00Commented Jan 16, 2014 at 22:50
-
$\begingroup$ @IlmariKaronen, actually, I quite like it over all. Would you might if I incorporate something similar into the begingroup extension directly? You use an approach I hadn't thought of, and I think it works nicely (as you point out). BTW, there are a couple of other things that could be added to SOUP that I might suggest, but this is not the right pace for that. Where is best to discuss such things? $\endgroup$Davide Cervone– Davide Cervone2014年01月17日 14:38:41 +00:00Commented Jan 17, 2014 at 14:38
This answer will serve as a demonstration:
$$\sin \pi = 0$$
What I typed was true (edit or view source), but what you see is false.
-
3$\begingroup$ When $\sin$ is $\sin$ and $\cos$ is $\sin$! Pythagoras rolls over in his unmarked grave. $\endgroup$2012年05月04日 22:38:13 +00:00Commented May 4, 2012 at 22:38
$\require{begingroup} \begingroup$As discussed in the comments to Davide Cervone's answer, I have added a client-side fix to this bug to version 1.2. of the Stack Overflow Unofficial Patch.
The fix works by injecting a special hidden TeX command (currently named \resetstack
) at the beggining of each post, comment, snippet (as shown e.g. on the front page) or question/answer link (as in the sidebar), which resets the TeX InputJax macro definitions to their default values.
The implementation is currently a bit complicated, but hopefully it can be simplified later, if some of the needed code is incorporated directly into MathJax as Davide suggests in the comments.
Some important notes about the fix:
Since SOUP is a client-side user script, installing it will fix the bug for you, but not for others. In particular, any definitions made in your posts will still leak to other posts when viewed by users who don't have SOUP installed (which, alas, means most of them).
I therefore strongly recommend that, if you use \def
, \(re)newcommand
or other such features in your posts, you should always prefix them with:
$\require{begingroup} \begingroup$
and end them with:
$\endgroup$
to keep your definitions from leaking into other posts. (Note that using SOUP should eliminate any memory leak issues due to unclosed \begingroup
tags while composing a post, since SOUP will reset the definition stack whenever the preview pane is re-typeset.)
You should also avoid redefining symbols in question titles, or anywhere near the top of your posts where the definitions would be likely to show up on the front page or in search results. (Alas, there's currently no 100% reliable way to prevent that from happening, except by not redefining TeX commands at all.)
Because of these issues, \def
and friends are still best used sparingly, and only for things that would be unlikely to conflict with notation in other posts. For example, \newcommand{\foo}{\operatorname{foo}}
is probably fine, but \newcommand{\sin}{\cos}
is not.
Also note that, even with SOUP, definitions imported from extensions via \require
will still leak into other posts. This is pretty much impossible to avoid without breaking some extensions badly, and should basically be considered as being by design.$\endgroup$
Edit: Turns out that my original implementation of this fix suffered from a race condition that made it work on Firefox only occasionally. This should be fixed in v1.2.1 that I just released; anyone using it is strongly advised to upgrade.
(Also, the upcoming v1.4 release of SOUP will have more MathJax scoping fixes, including one for \label
s, again based on a suggestion by Davide Cervone. Those still need some more testing before release, though.)
-
$\begingroup$ Is it possible that SOUP could implement some sort of autosave feature to prevent loss of work due to frequent Chrome + MathJax crashes? The problem is so severe that I don't even dare to use MathJax with Chrome any more (except for trivial answers), having already lost countless hours of work due to such crashes. $\endgroup$Bill Dubuque– Bill Dubuque2014年01月18日 15:56:34 +00:00Commented Jan 18, 2014 at 15:56
-
$\begingroup$ @Bill: The SE editor is already supposed to autosave posts, although only every 45 seconds. Of course, the real problem here is MathJax crashing Chrome, which presumably counts as a bug in both MathJax and Chrome. FWIW, I suspect things may have improved somewhat -- I use both Firefox and Chrome, and do recall experiencing poor rendering and slowdowns during editing (if not outright crashes) on the latter in the past, but not so much recently (except on the Android version of Chrome, which does get bogged down by lots of math). $\endgroup$Ilmari Karonen– Ilmari Karonen2014年01月18日 16:04:43 +00:00Commented Jan 18, 2014 at 16:04
-
$\begingroup$ Alas, the SE "autosave" feature is a kludge that works only rarely to recover from Chrome crashes. Any heavy use of MathJax + Chrome causes frequent Chrome crashses, making MathJax essentially unusable on Chrome. It's been this way for many years now. If it cannot be fixed, it would be really, really great to have some workaround, if that is not too much trouble to implement. This is by far the worst software problem I've encountered in a few decades of heavy software use. It's a shame that it has gone on this long. You can see many complaints about it in old meta posts. $\endgroup$Bill Dubuque– Bill Dubuque2014年01月18日 16:47:38 +00:00Commented Jan 18, 2014 at 16:47
-
$\begingroup$ I agree. I can't really fix it without knowing why it happens, though, and I don't think anyone's really figured that out yet. (If someone has, please do tell me.) $\endgroup$Ilmari Karonen– Ilmari Karonen2014年01月18日 16:49:42 +00:00Commented Jan 18, 2014 at 16:49
-
$\begingroup$ I highly doubt it will ever happen. David claims it is a bug in Chrome tckled by MathJax. So the only hope is a workaround. Surely it must be very easy to implement a halfway decent autosave feature in SOUP, right? This would be the best thing since sliced bread. It would save many Chrome users countless hours of lost work. $\endgroup$Bill Dubuque– Bill Dubuque2014年01月18日 17:05:58 +00:00Commented Jan 18, 2014 at 17:05
-
$\begingroup$ It might be possible using LocalStorage, although if Chrome crashes badly enough, that might not be perfectly safe either. I've never actually used LocalStorage before, but I could take a look into it. I'd also have to find some way to keep it from fighting with the SE builtin autosave feature, though. $\endgroup$Ilmari Karonen– Ilmari Karonen2014年01月18日 17:11:15 +00:00Commented Jan 18, 2014 at 17:11
-
$\begingroup$ Thanks! Even something more primitive such as saving to the clipboard would be helpful. The goal is to guarantee that one will not lose much work even if the browser crashes (which is very far from true for the SE draft saving feature) $\endgroup$Bill Dubuque– Bill Dubuque2014年01月18日 17:36:00 +00:00Commented Jan 18, 2014 at 17:36
-
$\begingroup$ Javascript doesn't have access to the clipboard (for security reasons), so that is not likely to be a solution. There are some Flash-based kludges, but in general, browsers prevent javascript frmo modifying the clipboard. $\endgroup$Davide Cervone– Davide Cervone2014年01月18日 22:42:40 +00:00Commented Jan 18, 2014 at 22:42
Fun fact:
in addition to
\newcommand{\sin}{\cos}
you can also include
\newcommand{\cos}{\sin}
and flat-out break all the code that uses those commands. Or, if you felt inclined to be evil, you could e.g. do a cyclic redefinition of the entire Greek alphabet, or something. Not that you should, of course.
-
3$\begingroup$ How does this contribute to the discussion? $\endgroup$2017年03月16日 07:14:39 +00:00Commented Mar 16, 2017 at 7:14
-
6$\begingroup$ It illustrates how bad this bug is $\endgroup$Nick Alger– Nick Alger2017年06月21日 01:55:02 +00:00Commented Jun 21, 2017 at 1:55
-
1$\begingroup$ In case it is not obvious, this pair of definitions will not swap the roles of
\sin
and\cos
. Rather, it will make both macros unusable, as they are now defined by mutual recursion that never comes to an end, leading to a "MathJax maximum macro substitution count exceeded" error. $\endgroup$Emil Jeřábek– Emil Jeřábek2022年02月05日 10:33:02 +00:00Commented Feb 5, 2022 at 10:33
You must log in to answer this question.
Explore related questions
See similar questions with these tags.
\renewcommand
? I can understand\DeclareMathOperator
and\newcommand
which seem much less dangerous because clashes are rather unlikely, but I can't think of a really good use of\renewcommand
. $\endgroup$\newcommand
or\renewcommand
was in the comments? $$\renewcommand{\sin}{\left.{{\unicode{x263A}}\atop{\unicode{x263A}}}\right)}$$ $\endgroup$\geqslant
($\geqslant$) overgeq
($\geq$) and thus write\let\geq\geqslant
in the beginning of my posts. (I don't want to write\geqslant
every time.) Same with\phi
($\phi$) and\varphi
($\varphi$). $\endgroup$$\DeclareMathOperator{\ran}{ran}\ran f=\emptyset$
to get $\DeclareMathOperator{\ran}{ran}\ran f=\emptyset$. $\endgroup$$\def\a{a}$ \a
results in a space, but$\def\a{a}$\a
doesn't. $\endgroup$