0
$\begingroup$

I am working on the fancy abstraction for Block function. The idea is to use rules to specify which local variable will be used, even if it already defined in the global context

like this

str = "something in the global context"; 
localEval[str, "str"->"Hello"]

and the output will be

"Hello"

where the global definition of str remains untouched.

I came up with the following solution, that works well

localEval[exp_, vars___] := With[
 {args = With[{val = #[[2]]},
                  ToExpression[#[[1]], InputForm, Function[name, Hold[name = val], HoldAll]]
             ] & /@ List[vars]
 },
   
   Block[args,
     exp
     ] // ReleaseHold
   ];
SetAttributes[localEval, HoldFirst];

but for me it is not fancy, because firstly it creates an error message, which doesn't affect anything

Block::lvsym: Local variable specification {Hold[str=hello]} contains Hold[str=hello], which is not a symbol or an assignment to a symbol.

I assume that ReleaseHold firstly tries to evaluate Block with the first argument contained Hold expressions and only after that goes to release them.

How could it be improved? Also I am worrying about the possible performance issues due to the error messages generated.

$\endgroup$
6
  • 2
    $\begingroup$ Could you explain why Block, Module, or With don't work for your application? I find your approach rather baffling. $\endgroup$
    – MarcoB
    Apr 15 at 14:29
  • $\begingroup$ As Set has the attribute HoldFirst, ypou may simply define: localEval[str] = "Hello";` then localEval[str] will always return "Hello" independent of the value of str. $\endgroup$ Apr 15 at 14:54
  • $\begingroup$ Yeah, actually the good question. I originally tried to make it in the same way as in Block. like localEval[exp, {str = "Helo"}] with the Hold attribute on the argument, but it would not work in the case when localEval[exp, {str = somehting to evaluate}], the right part will not be evaluated, I guess. Of course, this is an simplified example, the real function inside is going to be more complicated. $\endgroup$ Apr 15 at 15:08
  • $\begingroup$ Daniel, thanks. But, I am a bit confused. Could you explain it how to implement it for a multiple arguments passing to the function? $\endgroup$ Apr 15 at 15:11
  • $\begingroup$ sorry. there are some extra problem, if i am trying to implement it as in the block localEval[exp_, vars___] := With[{v = List[vars]}, Block[v, exp]]; SetAttributes[localEval, HoldAll]; $\endgroup$ Apr 15 at 15:14

1 Answer 1

1
$\begingroup$

The community helped me to realize the better way for my application. Hah ;)

localEval[exp_, vars_:{}] := Block[vars, exp];
SetAttributes[localEval, HoldAll];

that't it

$\endgroup$

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.