5
$\begingroup$

I am using Block inside the definition of some recursive functions.

If the Block definitions use short variable names, like {s = First[param], r = Rest[param]}, an infinite recursion occurs when param contains one of the symbols s or r.

Using tortured local symbols names minimizes this risk, but

  • it makes code unreadable,
  • it does not prevent the collision risk, but only minimizes it.

How to deal with local variable assignment without any collision risk?

Substitution rules and Modules have their own problems with recursive functions, which is why I use Blocks, but it's maybe the wrong tool.

Edit: There is no good reason not to use Module, except if one wants to locally modify the recursion limit, it seems. For my part, I was just confused, and I should just use Module.

$\endgroup$
21
  • 3
    $\begingroup$ What is the problem with using Module? I think it would be the right tool here. $\endgroup$
    – celtschk
    May 4, 2012 at 7:41
  • 1
    $\begingroup$ When there's a chance that symbols will be passed to your function, and you have no control over what those symbols might be (i.e. it's an end-user accessible function), then Block is almost never a good solution. So what's wrong with Module? It seems to me that Module is the way to go here, but you didn't explain what the problem is with it. $\endgroup$
    – Szabolcs
    May 4, 2012 at 7:42
  • 2
    $\begingroup$ Why don't you provide a complete minimal self-contained example of what you are trying to achieve and which problems you encounter. Your current question does not contain enough information for a meaningful answer. $\endgroup$ May 4, 2012 at 7:45
  • 2
    $\begingroup$ @ruebenko Personally, I tend to rewrite my code in a tail-recursive style as soon as I discover a need to change the $RecursionLimit - it is all to easy to crash the kernel resetting this value, and I would not trust the code which does that. $\endgroup$ May 4, 2012 at 7:51
  • 2
    $\begingroup$ If you absolutely must use Block and cannot use Module, put the local variable symbols in a private context: Begin["myfun`"]; myfun[x_] := Block[{s=1}, x+s]; End[]. Now myfun[s] will return s+1 as expected. $\endgroup$
    – Szabolcs
    May 4, 2012 at 7:51

1 Answer 1

7
$\begingroup$

If you don't want to have the Module inside the function, you can also put it around the function, and then use Block inside, as in

Module[{s,r},
  f[param_List]:=Block[{s = First[param], r = Rest[param]}, ... ]
]

However, for this special case, I'd use the abilities of the pattern matcher:

f[{s_,r___}] := ...
$\endgroup$
2
  • $\begingroup$ Thanks, I actually can use Module, I was confused. I will edit my question to clarify that and accept your answer :) $\endgroup$
    – agravier
    May 5, 2012 at 18:51
  • $\begingroup$ @agravier: Thank you for the accept. $\endgroup$
    – celtschk
    May 5, 2012 at 19:51

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.