Please explain this behavior of With, Block and Module - wolfram-mathematica

Good day,
I'm puzzled a bit with this:
In[1]:= f[x_]:=With[{xx=x},f[xx_]:=ff[xx]]
DownValues[f]
f[1]
DownValues[f]
Out[2]= {HoldPattern[f[x_]]:>With[{xx=x},f[xx_]:=ff[xx]]}
Out[4]= {HoldPattern[f[xx_]]:>ff[xx]}
The same happens if I use Block or Module instead of With.
I expected that the last DownValues[f] will give: {HoldPattern[f[x_]]:>ff[x]}. But it does not. Please, explain.

From documentation of With.
With replaces symbols in expr only when they do not occur as local variables inside scoping constructs.
Module and Block are simply not meant to do it.
Edit to elaborate on Module and Block. `The reason symbol is not replaced, is that it is not being evaluated. Block and Module do not do syntactic replacement operations. Try
f[x_] := Block[{xx = x}, f[xx_] = ff[xx]]
and then evaluate f[z].
Alternatively, you can execute you initial strategy by first using non-scoping construct:
f[x_] := With[{xx = x},
Hold[{f[xx_], ff[xx]}] /. {Hold[{a_, b_}] :> SetDelayed[a, b]}]
In[117]:= DownValues[f]
Out[117]= {HoldPattern[f[x_]] :>
With[{xx = x},
Hold[{f[xx_], ff[xx]}] /. {Hold[{a_, b_}] :> (a := b)}]}
In[118]:= f[z]
In[119]:= DownValues[f]
Out[119]= {HoldPattern[f[z_]] :> ff[z]}

Related

SymbolName applied to a list of variables, some of which may have values assigned

In Mathematica:
I would like to pass a variable number of arguments to a function.
I would like to print the name of each argument. The problem is that SymbolName evaluates its input. For a given variable, you can get around this:
a=18;
SymbolName[Unevaluated[a]]
works. But that won't work if the variable is in a list. For example:
printname[x__]:=Print[Table[SymbolName[Unevaluated[{x}[[i]]]],{i,1,Length[{x}]}]];
printname[a,b,c]
will not work. Any suggestions?
Thanks in advance.
Mathematica tries to evaluate the argument of Unevaluated[] when you call it. So {x}[[i]] gets converted into {18, b, c}[[i]] which you didn't want and then the iteration over i doesn't work anymore because Unevaluated[] doesn't let the Table access the iterator.
So, to really solve the issue you should disable Mathematica's evaluation completely for the functions that you want to pass the symbols through.
In[1]:= SetAttributes[SymbolName, HoldAll];
SetAttributes[Map, HoldAll];
After this you can just do
In[2]:= a=18; SymbolName ### Unevaluated /# {a, b, c}
Out[2]:= {a, b, c}
where ### and /# are shorthand for Apply[] and Map[].
Setting Hold[] or similar attributes in Mathematica's built in functions can lead to trouble. See this question and answer in the Mathematica stackexchange for more information.
Specifically, to make a function that takes an arbitrary number of arguments would be
sym = SymbolName ### Unevaluated /# {##} &
But the List[] function that takes the sequence of arguments ## for the function & will again evaluate a and turning HoldAll on for List[] is not OK.
Thus the easiest way to do this is to define a function with HoldAll that just passes the args into a Block[] as the list of local variables. This makes a creates an isolated context where the variables do not evaluate to anything.
In[1]:= SetAttributes[f, HoldFirst];
In[2]:= f[seq__] := Block[{seq}, Print[SymbolName /# {seq}]];
In[3]:= a=18; f[a, b, c]
Out[3]:= {a, b, c}

How to fix syntax to nest functions in mathematica?

I wanted to try to make a rule to do norm squared integrals. For example, instead of the following:
Integrate[ Conjugate[Exp[-\[Beta] Abs[x]]] Exp[-\[Beta] Abs[x]],
{x, -Infinity, Infinity}]
I tried creating a function to do so, but require the function to take a function:
Clear[complexNorm, g, x]
complexNorm[ g_[ x_ ] ] := Integrate[ Conjugate[g[x]] * g[x],
{x, -Infinity, Infinity}]
v = complexNorm[ Exp[ - \[Beta] Abs[x]]] // Trace
Mathematica doesn't have any trouble doing the first integral, but the final result of the trace when my helper function is used, shows just:
complexNorm[E^(-\[Beta] Abs[x])]
with no evaluation of the desired integral?
The syntax closely follows an example I found in http://www.mathprogramming-intro.org/download/MathProgrammingIntro.pdf [page 155], but it doesn't work for me.
The reason why your expression doesn't evaluate to what you expect is because complexNorm is expecting a pattern of the form f_[x_]. It returned what you put in because it couldn't pattern match what you gave it. If you still want to use your function, you can modify it to the following:
complexNorm[g_] := Integrate[ Conjugate[g] * g, {x, -Infinity, Infinity}]
Notice that you're just matching with anything now. Then, you just call it as complexNorm[expr]. This requires expr to have x in it somewhere though, or you'll get all kinds of funny business.
Also, can't you just use Abs[x]^2 for the norm squared? Abs[x] usually gives you a result of the form Sqrt[Conjugate[x] x].
That way you can just write:
complexNorm[g_] := Integrate[Abs[g]^2, {x, -Infinity, Infinity}]
Since you're doing quantum mechanics, you may find the following some nice syntatic sugar to use:
\[LeftAngleBracket] f_ \[RightAngleBracket] :=
Integrate[Abs[f]^2, {x, -\[Infinity], \[Infinity]}]
That way you can write your expectation values exactly as you would expect them.

How to intercept assigning new value for the In variable?

I wish to intercept assigning new values for the In variable.
I have tried to do this by defining UpValues for In but it does not help in this case:
Unprotect[In];
In /: Set[In[line_], expr_] /; ! TrueQ[$InsideSet] :=
Block[{$InsideSet = True},
Print[HoldForm#HoldForm[expr]; Set[In[line], expr]]]
In /: SetDelayed[In[line_], expr_] /; ! TrueQ[$InsideSet] :=
Block[{$InsideSet = True},
Print[HoldForm#HoldForm[expr]; SetDelayed[In[line], expr]]]
Is it possible to intercept it?
P.S. This question has arisen as a part of previous question on the stage when Mathematica creates new Symbols.
EDIT
I would wish to intercept explicitly the assignment new DownValue for the In variable. $Pre executes after this assignment and after creating all new Symbols in the current $Context:
In[1]:= $Pre := (Print[Names["`*"]];
Print[DownValues[In][[All, 1]]]; ##) &
In[2]:= a
During evaluation of In[2]:= {a}
During evaluation of In[2]:= {HoldPattern[In[1]],HoldPattern[In[2]]}
Out[2]= a
Have you looked at $Pre and $PreRead?
$Pre is a global variable whose value, if set, is applied to every input expression.
$PreRead is a global variable whose value, if set, is applied to the text or box form of every input expression before it is fed to Mathematica.
UPDATE (now with better example)
In[1]:= $Pre =
Function[{x}, Print["In[",$Line,"] is: ", Unevaluated[x]]; x, HoldFirst];
In[2]:= 2 + 2
During evaluation of In[2]:= In[2] is: 2+2
Out[2]= 4
In[3]:= InString[2]
During evaluation of In[3]:= In[3] is: InString[2]
Out[3]= "\\(2 + 2\\)"
UPDATE 2
Replace $Pre with $PreRead in my code above and you get close to what you want, I believe:
In[1]:= $PreRead = Function[{x}, Print[Names["`*"]]; x, HoldFirst]
Out[1]= Function[{x}, Print[Names["`*"]]; x, HoldFirst]
In[2]:= a = 1
During evaluation of In[2]:= {x}
Out[2]= 1
In[3]:= b = 2
During evaluation of In[3]:= {a,x}
Out[3]= 2
It's not possible to intercept In at the *Value level because the Kernel is simply not interacting with In via value manipulation in "top-level" Mathematica code.

How to get all definitions associated with other symbols?

How to get all definitions for a symbol associated with other symbols by TagSet, TagSetDelayed, UpSet or UpSetDelayed?
For example, if one has defined
area[square] ^= s^2
area[cube] ^= 6*s^2
how to obtain these definitions, not knowing the names square, cube but knowing only the name area?
I just have found that UpValues does not return definitions for MakeBoxes and N since they are stored in FormatValues and NValues correspondingly:
In[1]:= rotate /: MakeBoxes[expr_rotate, "StandardForm"] := x
UpValues[rotate]
FormatValues[rotate]
Out[2]= {}
Out[3]= {HoldPattern[MakeBoxes[expr_rotate, "StandardForm"]] :> x}
In[4]:= pi /: N[pi] = 3.14
UpValues[pi]
NValues[pi]
Out[4]= 3.14
Out[5]= {}
Out[6]= {HoldPattern[N[pi, {MachinePrecision, MachinePrecision}]] :>
3.14}
In this way instead of UpValues we should use a combination of UpValues, FormatValues and NValues.
When trying to output a list of FormatValues one can face problems with MakeBoxes since FormatValues gives definitions for MakeBoxes those are further processed by MakeBoxes on creating the output for the FrontEnd. This problem can be solved by switching FormatType temporarily to OutputForm or by converting these definitions to strings.
In[1]:= SetOptions[$Output,FormatType->OutputForm];
FormatValues[DialogNotebook]
Out[2]= {HoldPattern[MakeBoxes[BoxForm`apat$:HoldPattern[DialogNotebook[___]], BoxForm`fpat$_]] :>
BoxForm`BoxFormAutoLoad[MakeBoxes, BoxForm`apat$, BoxForm`fpat$, Typeset`CellNotebook`,
{{CellGroup, _}, {DocumentNotebook, _}, {PaletteNotebook, _}, {DialogNotebook, _}, {ExpressionCell, _}, {Text, _},
{TextCell, _}, {Cell, HoldPattern[MakeExpression[_Cell, _]]}, {Notebook, HoldPattern[MakeExpression[_Notebook, _]]}}]}
In[1]:= ToString#FormatValues[DialogNotebook]
Out[1]= {HoldPattern[MakeBoxes[BoxForm`apat$:HoldPattern[DialogNotebook[___]], BoxForm`fpat$_]] :> BoxForm`BoxFormAutoLoad[MakeBoxes, BoxForm`apat$, BoxForm`fpat$, Typeset`CellNotebook`, {{CellGroup, _}, {DocumentNotebook, _}, {PaletteNotebook, _}, {DialogNotebook, _}, {ExpressionCell, _}, {Text, _}, {TextCell, _}, {Cell, HoldPattern[MakeExpression[_Cell, _]]}, {Notebook, HoldPattern[MakeExpression[_Notebook, _]]}}]}
Attempting to address Alexey's concerns with Howard's answer, I came up with this:
Cases[
UpValues ### MakeExpression /# Names["Global`*"],
HoldPattern[_#_area :> _],
{2}
]
In response to your updated requirements, here is the advanced version:
SetAttributes[otherValues, HoldFirst]
otherValues[sym_] :=
With[{names = MakeExpression /# Names["Global`*"]},
Join[
Cases[UpValues ### names, HoldPattern[_#_sym :> _], {2}],
Cases[NValues ### names, HoldPattern[_#N[sym, ___] :> _], {2}],
Select[Join ## FormatValues ### names, ! FreeQ[#, HoldPattern#sym] &]
]
]
You can try an exhaustive search via
Select[UpValues /# Cases[ToExpression[Names["*"]], _Symbol], ! FreeQ[#, area] &]
which in your example will yield
{{HoldPattern[area[cube]] :> 6 s^2}, {HoldPattern[area[square]] :> s^2}}
The following version
Cases[
Flatten#Map[
ToExpression[#, InputForm, Function[sym, UpValues[sym], HoldAllComplete]] &,
Names["Global`*"]],
Verbatim[RuleDelayed][Verbatim[HoldPattern][_area], _]
]
will not evaluate symbols as well. It is similar in spirit to #Mr. Wizard's answer, but I prefer ToExpression to MakeExpression since the latter is tied to the FrontEnd and boxes ( at least conceptually) , while the former is a general-purpose command (although it is mentioned in the documentation that it will use rules for MakeExpression).
If you have an access to the full Mathematica session from the start, another solution would be to overload TagSet, TagSetDelayed, UpSet and UpSetDelayed so that they will record the symbol dependencies in some kind of hash. Here is an example for UpSet:
Unprotect[UpSet];
Module[{tried, upsetHash},
upsetHash[_] = {};
getUpsetHash[] := upsetHash;
UpSet[f_[args___], rhs_] :=
Block[{tried = True},
AppendTo[upsetHash[f],
Select[HoldComplete[args],
Function[Null, Head[Unevaluated[#]] === Symbol, HoldAll]]];
UpSet[f[args], rhs]] /; ! TrueQ[tried]
];
Protect[UpSet];
All assignments made with UpSet after this redefinition will be recorded. For example, after executing your example above, you can call
In[6]:= getUpsetHash[][area]
Out[6]= {HoldComplete[square], HoldComplete[cube]}
This way you get your information much faster, especially if you want to make such inquiries frequently, and/or you have lots of packages loaded. You can also automate the process further, to switch to the standard definitions for assignments once you load the functionality of interest.

Using `With` with a list of `Rules` - but without affecting the normal behaviour of `With`

Say I have a list of Rules
rules = {a -> b, c -> d};
which I use throughout a notebook. Then, at one point, it makes sense to want the rules to apply before any other evaluations take place in an expression. Normally if you want something like this you would use
In[2]:= With[{a=b,c=d}, expr[a,b,c,d]]
Out[2]= expr[b, b, d, d]
How can I take rules and insert it into the first argument of With?
Edit
BothSome solutions fail do all that I was looking for - but I should have emphasised this point a little more. See the bold part above.
For example, let's look at
rules = {a -> {1, 2}, c -> 1};
If I use these vaules in With, I get
In[10]:= With[{a={1,2},c=1}, Head/#{a,c}]
Out[10]= {List,Integer}
Some versions of WithRules yield
In[11]:= WithRules[rules, Head/#{a,c}]
Out[11]= {Symbol, Symbol}
(Actually, I didn't notice that Andrew's answer had the Attribute HoldRest - so it works just like I wanted.)
You want to use Hold to build up your With statement. Here is one way; there may be a simpler:
In[1]:= SetAttributes[WithRules, HoldRest]
In[2]:= WithRules[rules_, expr_] :=
With ## Append[Apply[Set, Hold#rules, {2}], Unevaluated[expr]]
Test it out:
In[3]:= f[args___] := Print[{args}]
In[4]:= rules = {a -> b, c -> d};
In[5]:= WithRules[rules, f[a, c]]
During evaluation of In[5]:= {b,d}
(I used Print so that any bug involving me accidentally evaluating expr too early would be made obvious.)
I have been using the following form of WithRules for a long time. Compared to the one posted by Andrew Moylan, it binds sequentially so that you can say e.g. WithRules[{a->b+1, b->2},expr] and get a expanded to 3:
SetAttributes[WithRules, HoldRest]
WithRules[rules_, expr_] := ReleaseHold#Module[{notSet}, Quiet[
With[{args = Reverse[rules /. Rule[a_, b_] -> notSet[a, b]]},
Fold[With[{#2}, #1] &, Hold#expr, args]] /. notSet -> Set,
With::lvw]]
This was also posted as an answer to an unrelated question, and as noted there, it has been discussed (at least) a couple of times on usenet:
A version of With that binds variables sequentially
Add syntax highlighting to own command
HTH
EDIT: Added a ReleaseHold, Hold pair to keep expr unevaluated until the rules have been applied.
One problem with Andrew's solution is that it maps the problem back to With, and that does not accept subscripted variables. So the following generates messages.
WithRules[{Subscript[x, 1] -> 2, Subscript[x, 2] -> 3},
Power[Subscript[x, 1], Subscript[x, 2]]]
Given that With performs syntactic replacement on its body, we can set WithRules alternatively as follows:
ClearAll[WithRules]; SetAttributes[WithRules, HoldRest];
WithRules[r : {(_Rule | _RuleDelayed) ..}, body_] :=
ReleaseHold[Hold[body] /. r]
Then
In[113]:= WithRules[{Subscript[x, 1] -> 2,
Subscript[x, 2] -> 3}, Subscript[x, 1]^Subscript[x, 2]]
Out[113]= 8
Edit: Addressing valid concerns raised by Leonid, the following version would be safe:
ClearAll[WithRules3]; SetAttributes[WithRules3, HoldRest];
WithRules3[r : {(_Rule | _RuleDelayed) ..}, body_] :=
Developer`ReplaceAllUnheld[Unevaluated[body], r]
Then
In[194]:= WithRules3[{Subscript[x, 1] -> 2, Subscript[x, 2] -> 3},
Subscript[x, 1]^Subscript[x, 2]]
Out[194]= 8
In[195]:= WithRules3[{x -> y}, f[y_] :> Function[x, x + y]]
Out[195]= f[y_] :> Function[x, x + y]
Edit 2: Even WithRules3 is not completely equivalent to Andrew's version:
In[206]:= WithRules3[{z -> 2}, f[y_] :> Function[x, x + y + z]]
Out[206]= f[y_] :> Function[x, x + y + z]
In[207]:= WithRules[{z -> 2}, f[y_] :> Function[x, x + y + z]]
Out[207]= f[y$_] :> Function[x$, x$ + y$ + 2]

Resources