0

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.

Kirill Vasin
  • 1,235
  • 12
  • 14
  • 2
    Could you explain why Block, Module, or With don't work for your application? I find your approach rather baffling. – MarcoB Apr 15 '22 at 14:29
  • As Set has the attribute HoldFirst, ypou may simply define:localEval[str] = "Hello";thenlocalEval[str]` will always return "Hello" independent of the value of str. – Daniel Huber Apr 15 '22 at 14:54
  • 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.

    – Kirill Vasin Apr 15 '22 at 15:08
  • Daniel, thanks. But, I am a bit confused. Could you explain it how to implement it for a multiple arguments passing to the function? – Kirill Vasin Apr 15 '22 at 15:11
  • 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];

    – Kirill Vasin Apr 15 '22 at 15:14
  • Related: https://mathematica.stackexchange.com/a/32791, https://stackoverflow.com/a/6236264 – Michael E2 Apr 15 '22 at 15:40

1 Answers1

1

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

Kirill Vasin
  • 1,235
  • 12
  • 14