3
$\begingroup$

I think the simplest way to state my question is to give an example:

x=2;
f[x_]:= x;

(* Is this possible? *)
f[x]
(* x *)

In other words, is it possible to stop Mathematica from evaluating x as 2 before evaluating the function? None of the Hold attributes or functions have successfully halted this part of evaluation for me.

What I'm trying to do is pass symbols to a function for it to manipulate, but I don't want to worry about the same symbol names being used in other parts of the code. Using Clear works, but it then requires me to re-evaluate the areas where the symbol name was used before, so I was hoping there was an easier way other than clearing or using different symbol names.

Edit: Sorry for the confusion. m_goldberg correctly guessed what I was trying to explain. Although I can hide global variables in Module blocks by using the same variable names, I was hoping for the same results with a function. Here is his code that represents my goal:

x = 2;
SetAttributes[f,HoldFirst]
f[x_]:= Module[{u = Defer[x]}, 1 + u + u^2];

f[x]

1 + x + x^2

In other words, I wanted to arbitrarily pick symbols as arguments to a function, regardless if they had been assigned values prior to calling my function. Apparently, I was looking for Defer.

I think it's worth noting that jjc385's answer also achieved my goal, but with a hold on the result.

Thank you everybody for the help!

$\endgroup$
4
  • 3
    $\begingroup$ If f is e.g. HoldFirst then x is not evaluated before f's rules are applied. But later, nothing stops it, you can add f[x_]:= Hold[x]; or something. Could you elaborate on what is the goal? $\endgroup$
    – Kuba
    May 18, 2017 at 21:24
  • $\begingroup$ I'm trying to make a function that takes in 2 lists, one being a list of equations and the latter being a list of variables. I then manipulate those symbolic variables and equations with other functions and rules and such. I was just hoping there was a way to arbitrarily pick variable names without disrupting other parts of my code, similar to a namespace in other programming languages, but I'll survive if it's not possible. I'm assuming Hold[function_body] may work, but then the assigned symbols would be evaluated immediately after. I would check but I'm not at my work computer currently. $\endgroup$
    – Anthony
    May 18, 2017 at 23:19
  • $\begingroup$ It sounds like you want the scoping that Module provides...? $\endgroup$ May 19, 2017 at 7:19
  • $\begingroup$ Please provide a small example of input, transformations, expected output. Otherwise we are just guessing. $\endgroup$
    – Kuba
    May 19, 2017 at 11:09

2 Answers 2

1
$\begingroup$

Perhaps this is what you are looking for.

The normal evaluation of arguments can be overridden by giving a function the appropriate Hold... attribute.

x = 2;
SetAttributes[f, HoldFirst]
f[x_] := Module[{u = Defer[x]}, 1 + u + u^2]

f[x]

1 + x + x^2

$\endgroup$
3
$\begingroup$

It's not entirely clear what you want, but perhaps this is a start.

Based on your comment, it seems like you may be roughly trying to mimic the behavior of either Module or Block :

(* x, y already have explicit values *)
x=1;
y=2;

Module[{x, y},
 First @ Solve[{x + y == 5, x - y == 1}, {x, y}]
]
{3, 2}

If the returned expression doesn't depend on any of the previously defined variables (as is the case above), Module and Block should give you the same output.

If the returned expression does depend on the previously defined variables, neither output may be desirable:

(* x, y already have explicit values *)
x=1;
y=2;

Module[{x, y},
 First @ Solve[{x + y == 5, x - y == 1}, {x, y}]
]
{x$9834 -> 3, y$9834 -> 2}
Block[{x, y},
 First @ Solve[{x + y == 5, x - y == 1}, {x, y}]
]
{1 -> 3, 2 -> 2}

I'm guessing you won't ever want the Block-style output. You can mitigate this using Hold:

Block[{x, y},
 Hold @@ {First @ Solve[{x + y == 5, x - y == 1}, {x, y}]}
]
Hold[{x -> 3, y -> 2}]

You can see I've used the trick of Applying (@@ing) Hold to {expr}, so that expr evaluates before getting wrapping in Hold.

You can turn this into a function using something like

ClearAll[myBlock]
SetAttributes[myBlock, HoldAll]

myBlock[varList_List, expr_] :=
 Block[varList,
  Hold @@ {expr}
 ]

Then you can do what you asked for in your original question, albeit with a Hold wrapper:

myBlock[{x}, f[x]]
 Hold[x]
$\endgroup$
2
  • $\begingroup$ replacing Hold with HoldForm at least in this case produces the desired output f[x]. loved your trick btw. i can see using it for my inspect function which produces an Echo with an automatically generated label for Symbols but does not play well with arguments which are patterns. i use for quick and dirty debugging inside function definitions and native structures. $\endgroup$ Apr 28, 2022 at 7:11
  • $\begingroup$ @Jules I'm glad to hear this post could help someone ~5 years later :) $\endgroup$
    – jjc385
    Apr 28, 2022 at 11:01

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.