0
$\begingroup$

Say I've got a function f[x_] := a x^2 + b*x + c; and later set for some other reason a=1; how can I get the expression of f in an untouched form (with "a" and not "1")?

I don't want to use HoldForm or Unevaluated in definition of f nor parse Definition[f].

An example code that I'm trying to modify, so that it ignores evaluation of symbols in the first 2 StylePrints.

SetAttributes[DD, HoldFirst];
DD[f_, var_] := HoldForm[\!\(\*SubscriptBox[\(\[PartialD]\), \(var\)]f\)];

SetAttributes[CSE, HoldFirst];
CSE[e_] := 
  ToExpression[
   If[StringFreeQ[ToString[HoldForm@e], "Subscript["], 
    "\[CapitalDelta]" <> ToString[HoldForm@e] <> "", 
    StringReplace[ToString[HoldForm@e], 
     "Subscript[" -> "Subscript[\[CapitalDelta]"]], TraditionalForm, 
   HoldForm];

SetAttributes[TDE, HoldFirst];
TDE[fun2_, vars2__] := 
  Sqrt[Sum[i, {i, ((CSE[#] DD[fun2, #])^2) & /@ vars2}]];

SetAttributes[TotalDiffrentialError, HoldFirst];
TotalDiffrentialError[fun_, vars__] := Module[{Expanded},
   StylePrint[CSE[fun] == TDE[fun, vars], "EquationNumbered"];
   StylePrint[CSE[fun] == FullSimplify[ReleaseHold[TDE[fun, vars]]], 
    "EquationNumbered"];
   FullSimplify[ReleaseHold[TDE[fun, vars]]]];

So what I'm trying to do with that is to print elegant equations without numerical values, up to a certain point when (in current implementation) I release all the Holds. This design would in theory let me to define values somewhere before and not bother about passing them to the function.

$\endgroup$
  • 3
    $\begingroup$ Given that you've basically ruled out most practical approaches to solving your problem, would you care to elaborate on exactly what you expect a solution to look like? $\endgroup$ – Oleksandr R. May 9 '14 at 19:35
  • 2
    $\begingroup$ With all the restrictions you made, your problem is kind of equivalent of keeping 1+1 from turning into 2. Without interfering with Mathematica's evaluation process or other trickery which makes that it only looks like you get what you want, this is not possible. Can you please give a practical reason what you try to achieve? $\endgroup$ – halirutan May 9 '14 at 19:46
  • 2
    $\begingroup$ DownValues[f] /. RuleDelayed[a_, b_] :> HoldForm[b] is just one way of getting at this, but I must agree with other comments: what is the purpose and why are you trying to circumvent the basic semantics of the language? $\endgroup$ – ciao May 9 '14 at 19:48
  • 1
    $\begingroup$ SetAttributes[TotalDerivative, HoldAll]; TotalDerivative[f_,vars:{__Symbol}] := Block[vars, {whatever}]... for what reason is that problematic? $\endgroup$ – Oleksandr R. May 9 '14 at 20:01
  • 3
    $\begingroup$ You will save yourself a lot of trouble if you don't define functions whose bodies depend on global variables. In that case, all this would've been unnecessary. I suggest that you look at this answer, where I discussed this in detail. $\endgroup$ – Leonid Shifrin May 9 '14 at 20:07
3
$\begingroup$

On CSE

If you want to work with symbolic representation of changes in functions or variables you probably don't want that object (cse) to evaluate to something wrapped in HoldForm with parts modified with "Subscript[" -> "Subscript[\[CapitalDelta]" rule.

(BTW, it's not even clear what is the result of it. CSE[x] // FullForm looks very weird, for example: there is no space between CapitalDelta and x, and it's not even interpreted as a proper expression when inside HoldForm. It's quite alarming, IMO.) I get it now, sorry. CSE@x is a new symbol, x written with greek prefix. Arguably, mixing greek and latin in symbols names is not a proper way to go—certainly so if the core reason for this is pretty printing, which I suspect is the case.

If you just want changes in variables pretty printed then I promise you will enjoy MakeBoxes:

MakeBoxes[cse[Subscript[x_, sub_]], opt_] ^:= 
SubscriptBox[
  RowBox@{"\[CapitalDelta]", MakeBoxes[x, opt]}
, MakeBoxes[sub, opt]]

MakeBoxes[cse[x_], opt_] ^:= 
RowBox@{"\[CapitalDelta]", MakeBoxes[x, opt]}

It looks like this:

In[1]:= cse[Subscript[x, 1]]
Out[1]= Subscript[\[CapitalDelta] x, 1]

On global variables

As Leonid Shifrin noted in comments, definitions with global variables in the rhs are shortcuts to disasters of all sorts. If you want to leave as much as possible non-localized, and also avoid HoldForm and Unevaluated, I suspect solutions will invariably turn out to be rather weird:

In[2]:= SetAttributes[f, HoldRest]

In[3]:= f[x_, leadingCoeff : _ : a] := 
        With[{cachedA = a}, 
        Clear@a; ({leadingCoeff x^2 + b x + c, 
        Hold[a = cachedA] /. Hold@Set[v_, v_] :> (## &[])}) /. {f_} :> f]

In[4]:= f@x
Out[4]= c + b x + a x^2

In[5]:= a = 1
Out[5]= 1

In[6]:= ReleaseHold@f@x /. {first_, ___} :> HoldForm@first
Out[6]= c + b x + a x^2

In[7]:= a
Out[7]= 1

I don't suggest you use this, of course (you'd have to wrap instances of f@x in ReleaseHold to not lose the value of a), I merely hope this will help you convince yourself to localize everything, and don't reject quoting. The only alternative seems to be a flood of [often unpredictable] side effects.

$\endgroup$
  • $\begingroup$ On CSE: Of course I'd love a solution based on MakeBoxes, however I tried hard and I failed. Since I really needed it I've implemented it the ugly way, awaiting for comments like this. However it's not exactly what I've been looking for. You see, the function of CSE was to create a new symbol starting from CapitalDelta. In case of your code it's not one, but two symbols. The solution for using global variables in fact looks really weird and far from what I'm looking for. What I'm aiming for is to create a define functions in traditional way, but have this one special "style" function that... $\endgroup$ – Ranza May 9 '14 at 23:13
  • $\begingroup$ prints them according to their definition. I'm going to put my code on GitHub together with some examples maybe this way it'll become more clear what I'm trying to achieve. My ultimate aim is to create a set of tools that will allow easy and fast creation of science/engineering reports. $\endgroup$ – Ranza May 9 '14 at 23:17
  • $\begingroup$ Yes, I was in doubt if I should post this answer at all. Sorry if it didn't help, my point is that your specs don't seem to leave much space for anything but clojure-like solutions. (I've dealt with this problem myself before.) Now I think it would be OK to delete this answer, especially if you don't find the MakeBoxes part useful. $\endgroup$ – Akater May 9 '14 at 23:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.