4
$\begingroup$

This problem is similar to this problem using package to verify solution of ode with Association, Naming scope/context handling but when I used the solution/trick given there, I still get a problem.

I am not well versed in low level package programming to figure what other tricks I need for this and it seems the solutions are way too complicated for me to understand.

Here is MWE. Given this package

BeginPackage["mypkg`"] 

Unprotect @@ Names["mypkg`*"]; 
ClearAll @@ Names["mypkg`*"]; 

dsolve::usage = "..."

Begin["`Private`"]     

    dsolve[y_,x_]:= Module[{assoc},
        assoc=<| "x"->x,"y"->y|>;
        process[assoc]
    ];           

    process[assoc_Association]:=Module[{x,y},
        x=assoc["x"];
        y=assoc["y"];
        Inactivate[Integrate[1/Log[1+K[1]^2],{K[1],0,y[x]}]]
    ];

End[]; 
Protect @@ Names["mypkg`*"]; 
EndPackage[]

And now

 SetDirectory[NotebookDirectory[]]
 Get["mypkg.m"]
 mypkg`dsolve[y, x]

Mathematica graphics

The solution given in the above link is to use @@ List[...] instead. So I replaced the line

 Inactivate[Integrate[1/Log[1+K[1]^2],{K[1],0,y[x]}]]

with

 Inactivate @@ List[Integrate[1/Log[1+K[1]^2],{K[1],0,y[x]}]]

And this did indeed fix the context issue, but now I get a new problem

 Get["mypkg.m"]
 mypkg`dsolve[y, x]

Mathematica graphics

You see, it tried to do the integration.

What I want is to use Inactivate to prevent the integral from evaluating but without the Private context showing up. i.e. I want the above output but with Mathematica actually doing the integral and getting this error, as I know this integral can't be integrated.

I am doing this so I can replace the form of the unevaluated integral to one with the upper limit being $y(x)$ as this is the form I prefer.

Any other tricks I should try?

V 13.2 on windows.

$\endgroup$
4
  • 3
    $\begingroup$ Here is it not about renaming but controlling evaluation, you need e.g. With[{upper = y[x]}, Inactivate[Integrate[1/Log[1 + K[1]^2], {K[1], 0, upper}]] ] like you would in x = 1; Hold[x] $\endgroup$
    – Kuba
    Commented Jan 25, 2023 at 5:46
  • $\begingroup$ @Kuba thanks, this worked. But isn't Inactivate supposed not to evaluate what is inside it in first place? Or does it evaluate some parts on its arguments first? may be I misunderstood Inactivate Note that in Global context this works as is without having to do With trick. i.,e. Inactivate[Integrate[1/Log[1 + K[1]^2], {K[1], 0, y[x]}]] works with no error. That is why I thought it is related to naming/context issue. !Mathematica graphics I do not think I will ever be able to understand fully Mathematica's evaluation/naming/contexts mixing... $\endgroup$
    – Nasser
    Commented Jan 25, 2023 at 5:53
  • $\begingroup$ @Kuba may be you can make this an answer, but with explanation of why With is needed inside the package and not needed outside the package as I am not able to figure it out myself. Thanks. $\endgroup$
    – Nasser
    Commented Jan 25, 2023 at 6:10
  • $\begingroup$ "in Global context this works as is without having to do With trick" No, the problem is still there. The following should help you see what's wrong: x = xx; y = yy; Inactivate[Integrate[1/Log[1 + K[1]^2], {K[1], 0, y[x]}]]. Also, if you just want to stop Integrate, it's better to write Inactivate[Integrate[1/Log[1 + K[1]^2], {K[1], 0, y[x]}], Integrate] (otherwise Inactivate will make almost every head Inactive) or simply Inactive[Integrate][1/Log[1 + K[1]^2], {K[1], 0, y[x]}]. These avoid the mentioned issue, too. $\endgroup$
    – xzczd
    Commented Jan 25, 2023 at 9:28

1 Answer 1

4
$\begingroup$

It is not really related to context although you see a full name of y because process was defined in that context and Module's y was parsed there. Not important really.

Even Module is not important although it manifests here in a $nnnnn number in the symbol name.

So let's strip package and Module from the case, and let's rename x, y to var and foo to avoid confusion from the fact that you have

local`x = <|"x" -> global`x|>

The issue boils down to the fact that Inactivate holds the whole expression initially and later keeps heads (foo/y) held. So those heads will stay as you specified them:

a = <|"x" -> x, "y" -> y|>;
var = a["x"];
foo = a["y"];
Inactivate[foo[var] + foo[var]] // InputForm

Inactive[Plus][Inactive[foo][x], Inactive[foo][x]]

We need to force evaluation but in many cases, like in yours, we need to be careful not to evaluate too much. There are many ways:

Inactivate[#[var] + #[var]] & @ foo

Inactivate[foo[var] + foo[var]] /. HoldPattern[foo] -> foo

but With is the most verbose I guess:

With[{foo = foo},
  Inactivate[foo[var] + foo[var]]
] // InputForm

Notice this is the same trick used with Dynamic programming:

See also:

$\endgroup$

Your Answer

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

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