3
$\begingroup$

Is it possible to detect the non-standard transformation rules (DownValues, UpValues, etc) that activate in an evaluation (and remove them)?

With non-standard I mean user defined, but the transformation rules assigned to Unprotected objects should be a good enough proxy for this.

So say I have assigned a downvalue for f, f[x_]:= x, and I input transformationDetection[f[1]] it would output the downvalue (and optionally remove that downvalue). Similarly if a chain of transformations are triggered it would output all of them (and optionally remove all of them).

$\endgroup$
4
  • 1
    $\begingroup$ I'm wondering what you'll want this for. Because I'm pretty sure in general, no, it's not really possible to detect only user-added *Values. But there might be an effective way to rephrase you problem to get around that. $\endgroup$
    – b3m2a1
    Jan 12, 2018 at 9:55
  • $\begingroup$ @b3m2a1, thanks for the reply. First of all, yes I'll edit user made to values assigned to Unprotected objects. It's use: It mainly would be a good debugging tool to have. $\endgroup$
    – Kvothe
    Jan 12, 2018 at 10:05
  • $\begingroup$ Okay. Well if you can figure out how to decide which *Values you want to work with, TraceScan will get the job done for you. Basically just write a testValuesl[expr] function to TraceScan over the evaluation tree. If it's just on Unprotected symbols your life is pretty good. Use testValues[s_Symbol?(Function[Null, FreeQ[Attributes[#], Protected], HoldFirst])[args__]]:=Echo[s] or something. $\endgroup$
    – b3m2a1
    Jan 12, 2018 at 10:12
  • $\begingroup$ @b3m2a1, I'm sorry but I don't quite understand how I'm supposed to implement this. Would you mind writing a full answer? Indeed the solution is probably a clever reconstruction of the rules used from the information in Trace or TraceScan. Still, it does not seem trivial to reconstruct the Values used from the information in Trace or TraceScan (and perhaps it is simply impossible). Yes: Unprotected is a valid interpretation of my answer. I included user-defined too because that is the true intent and for all I know there is some hidden attribute I don't know about that keeps track of that. $\endgroup$
    – Kvothe
    Jan 12, 2018 at 10:32

1 Answer 1

1
$\begingroup$

Maybe something like the following will work for you:

SetAttributes[transformationDetection,HoldAll]
transformationDetection[expr_] := Module[{syms},
    {syms, values} = Reap[
        Thread[
            Cases[
                Unevaluated@expr,
                x_Symbol?valuesQ :> Hold[x],
                {0, Infinity},
                Heads->True
            ],
            Hold
        ],
        _Symbol,
        Rule
    ];
    Print[values];
    Replace[syms,
        {
        {} :> expr,
        Hold[z_] :> Block[z, Hold @ Evaluate @ expr]
        }
    ]
]

SetAttributes[valuesQ, HoldAll]
valuesQ[sym_] := With[{def=Language`ExtendedDefinition[sym]},
    Cases[
        def, 
        rule:Rule[
            OwnValues|DownValues|UpValues|SubValues,
            Except[{}]
        ] :> Sow[rule, sym],
        {3}
    ] =!= {}
]

A couple examples:

f[x_]:=x^2
g[x_]:=1/x

transformationDetection[Integrate[f[x], {x, 1, g[3]}]]

transformationDetection[Integrate[x^2, {x, 1, g[3]}]]

{f->{DownValues->{HoldPattern[f[x_]]:>x^2}},g->{DownValues->{HoldPattern[g[x_]]:>1/x}}}

Hold[Integrate[f[x], {x, 1, g[3]}]]

{g->{DownValues->{HoldPattern[g[x_]]:>1/x}}}

Hold[-(1/3) + g[3]^3/3]

In the first example, the Integrate expression does not evaluate because the DownValues for f were removed by the Block.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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