This is very similar to a common problem that many symbolic Mathematica functions share, e.g.:
Solve[2*x-5==15,x]
and as can be seen from the example the standard way to solve that is to pass such symbols which are to be used as formal symbols as extra argument(s). As you guessed in your comment the most direct way to implement that would be something like:
BigStringExpr[someLetters_Symbol, anInteger_Symbol] :=
StartOfString ~~ someLetters : ToUpperCase@Alphabet[] .. ~~ "@" ~~
anInteger : (Except["0", DigitCharacter] ~~ DigitCharacter ...) ~~
EndOfString
which does work, as can be verified with e.g.:
StringReplace["ABC@123", BigStringExpr[a, b] :> StringJoin[b, "---", a]]
A remaining problem is, as you have noted, that a warning is issued at definition time and the syntax highlighting indicates the two names as a syntax error. That message and syntax error are there for understandable reasons as such definitions often not do what users actually want. But in this case it does exactly why we want, so we can safely ignore these warnings.
You found yourself one way to suppress the message, which of course is to just (temporarily) switch off that message with Off[RuleDelayed::rhs]
(and switch back on with On
after the definition). Newer versions provide the Quiet
function to provide exactly the possibility to "temporarily" switch off messages which is shorter and has the advantage to reset the originial state, no matter whether that was on or off. Leonid has shown you another version which avoids the message in the first place by inserting the symbols with With
:
bigStringExpr[someLetters_Symbol, anInteger_Symbol] :=
With[{sl = someLetters, int = anInteger},
StartOfString ~~ Pattern[sl, ToUpperCase@Alphabet[] ..] ~~ "@" ~~
Pattern[int, (Except["0", DigitCharacter] ~~ DigitCharacter ...)] ~~
EndOfString]
Actually that just "hides" the potential problem from Mathematica so that neither the syntax checker nor the messaging system actually complain. One could see this as just a trick which might fail when a more sophisticated future version of Mathematica will recognize such patterns as "dangerous" as well. So it probably is even cleaner to temporarily switch off the message. That will also be easier to read as it is clear why that part of the code is there at all, where you might have a hard time to find out what the With
was there when revisiting the code (a corresponding comment would then of course make sense).
One other thing I would improve (which is not directly related to the message/syntax highlighting) is to make that definition work even when there are definitions for the symbols you are using. First note that this won't work:
x=1;
BigStringExpr[x, y]
With adding:
SetAttributes[BigStringExpr,HoldAll]
you could make your function work even in that case which will make it somewhat more robust.
So for me the cleanest and most robust way to make such a definition seems to be:
Quiet[
SetAttributes[bigStringExpr,HoldAll];
bigStringExpr[someLetters_Symbol, anInteger_Symbol] := (
StartOfString ~~ someLetters : ToUpperCase@Alphabet[] .. ~~ "@" ~~
anInteger : (Except["0", DigitCharacter] ~~ DigitCharacter ...) ~~
EndOfString
),
RuleDelayed::rhs
]
You'll have to live with the syntax highlighting, but that seems OK for me as the Quiet
indicates that someone has noted the problem and decided it was OK to ignore the message (and the highlighting). Depending on the code quality requirements a corresponding comment would make sense...
BigStringExpr[someLetters_Symbol, anInteger_Symbol]:= StartOfString ~~ someLetters: ToUpperCase@Alphabet[] .. ~~ "@" ~~ anInteger: (Except["0", DigitCharacter] ~~ DigitCharacter ...) ~~ EndOfString
. It complains that the symbols already appear on the right-hand side. How would you pass in the symbols? May you provide and answer post, please. $\endgroup$bigStringExpr[someLetters_Symbol, anInteger_Symbol] := With[{sl = someLetters, int = anInteger }, StartOfString ~~ Pattern[sl, ToUpperCase@Alphabet[] ..] ~~ "@" ~~ Pattern[int, (Except["0", DigitCharacter] ~~ DigitCharacter ...)] ~~ EndOfString]
, whereWith
serves to full the system and avoid those complaints. $\endgroup$Off[RuleDelayed::rhs]
in the package just before definingBigStringExpr
and then turned them back on withOn[RuleDelayed::rhs]
immediately after. Thanks for the pass in the symbols idea. Making an answer post? $\endgroup$