# Tutorial :Reliable clean-up in Mathematica

### Question:

For better or worse, Mathematica provides a wealth of constructs that allow you to do non-local transfers of control, including `Return`, `Catch`/`Throw`, `Abort` and `Goto`. However, these kinds of non-local transfers of control often conflict with writing robust programs that need to ensure that clean-up code (like closing streams) gets run. Many languages provide ways of ensuring that clean-up code gets run in a wide variety of circumstances; Java has its `finally` blocks, C++ has destructors, Common Lisp has `UNWIND-PROTECT`, and so on.

In Mathematica, I don't know how to accomplish the same thing. I have a partial solution that looks like this:

``Attributes[CleanUp] = {HoldAll};  CleanUp[body_, form_] :=    Module[{return, aborted = False},     Catch[      CheckAbort[       return = body,       aborted = True];      form;      If[aborted,       Abort[],       return],      _, (form; Throw[##]) &]];  ``

This certainly isn't going to win any beauty contests, but it also only handles `Abort` and `Throw`. In particular, it fails in the presence of `Return`; I figure if you're using `Goto` to do this kind of non-local control in Mathematica you deserve what you get.

I don't see a good way around this. There's no `CheckReturn` for instance, and when you get right down to it, `Return` has pretty murky semantics. Is there a trick I'm missing?

EDIT: The problem with `Return`, and the vagueness in its definition, has to do with its interaction with conditionals (which somehow aren't "control structures" in Mathematica). An example, using my `CleanUp` form:

``CleanUp[   If[2 == 2,    If[3 == 3,     Return["foo"]]];   Print["bar"],     Print["cleanup"]]  ``

This will return "foo" without printing "cleanup". Likewise,

``CleanUp[   baz /.    {bar :> Return["wongle"],     baz :> Return["bongle"]},     Print["cleanup"]]  ``

will return "bongle" without printing cleanup. I don't see a way around this without tedious, error-prone and maybe impossible code-walking or somehow locally redefining `Return` using `Block`, which is heinously hacky and doesn't actually seem to work (though experimenting with it is a great way to totally wedge a kernel!)

### Solution:1

Great question, but I don't agree that the semantics of `Return` are murky; They are documented in the link you provide. In short, `Return` exits the innermost construct (namely, a control structure or function definition) in which it is invoked.

The only case in which your `CleanUp` function above fails to cleanup from a `Return` is when you directly pass a single or `CompoundExpression` (e.g. `(one;two;three)` directly as input to it.

Return exits the function `f`:

``In[28]:= f[] := Return["ret"]    In[29]:= CleanUp[f[], Print["cleaned"]]    During evaluation of In[29]:= cleaned    Out[29]= "ret"  ``

`Return` exits `x`:

``In[31]:= x = Return["foo"]    In[32]:= CleanUp[x, Print["cleaned"]]    During evaluation of In[32]:= cleaned    Out[32]= "foo"  ``

`Return` exits the `Do` loop:

``In[33]:= g[] := (x = 0; Do[x++; Return["blah"], {10}]; x)    In[34]:= CleanUp[g[], Print["cleaned"]]    During evaluation of In[34]:= cleaned    Out[34]= 1  ``

Returns from the body of `CleanUp` at the point where `body` is evaluated (since `CleanUp` is `HoldAll`):

``In[35]:= CleanUp[Return["ret"], Print["cleaned"]];    Out[35]= "ret"    In[36]:= CleanUp[(Print["before"]; Return["ret"]; Print["after"]),    Print["cleaned"]]    During evaluation of In[36]:= before    Out[36]= "ret"  ``

As I noted above, the latter two examples are the only problematic cases I can contrive (although I could be wrong) but they can be handled by adding a definition to `CleanUp`:

``In[44]:= CleanUp[CompoundExpression[before___, Return[ret_], ___], form_] :=              (before; form; ret)    In[45]:= CleanUp[Return["ret"], Print["cleaned"]]    During evaluation of In[46]:= cleaned    Out[45]= "ret"    In[46]:= CleanUp[(Print["before"]; Return["ret"]; Print["after"]),    Print["cleaned"]]    During evaluation of In[46]:= before    During evaluation of In[46]:= cleaned    Out[46]= "ret"  ``

As you said, not going to win any beauty contests, but hopefully this helps solve your problem!

I would argue that using `Return` inside `If` is unnecessary, and even an abuse of `Return`, given that `If` already returns either the second or third argument based on the state of the condition in the first argument. While I realize your example is probably contrived, `If[3==3, Return["Foo"]]` is functionally identical to `If[3==3, "foo"]`

If you have a more complicated `If` statement, you're better off using `Throw` and `Catch` to break out of the evaluation and "return" something to the point you want it to be returned to.

That said, I realize you might not always have control over the code you have to clean up after, so you could always wrap the expression in `CleanUp` in a no-op control structure, such as:

``ret1 = Do[ret2 = expr, {1}]  ``

... by abusing `Do` to force a `Return` not contained within a control structure in `expr` to return out of the `Do` loop. The only tricky part (I think, not having tried this) is having to deal with two different return values above: `ret1` will contain the value of an uncontained `Return`, but `ret2` would have the value of any other evaluation of `expr`. There's probably a cleaner way to handle that, but I can't see it right now.

HTH!

### Solution:2

Pillsy's later version of CleanUp is a good one. At the risk of being pedantic, I must point out a troublesome use case:

``Catch[CleanUp[Throw[23], Print["cleanup"]]]  ``

The problem is due to the fact that one cannot explicitly specify a tag pattern for Catch that will match an untagged Throw.

The following version of CleanUp addresses that problem:

``SetAttributes[CleanUp, HoldAll]  CleanUp[expr_, cleanup_] :=    Module[{exprFn, result, abort = False, rethrow = True, seq},      exprFn[] := expr;      result = CheckAbort[        Catch[          Catch[result = exprFn[]; rethrow = False; result],          _,          seq[##]&        ],        abort = True      ];      cleanup;      If[abort, Abort[]];      If[rethrow, Throw[result /. seq -> Sequence]];      result    ]  ``

Alas, this code is even less likely to be competitive in a beauty contest. Furthermore, it wouldn't surprise me if someone jumped in with yet another non-local control flow that that this code will not handle. Even in the unlikely event that it handles all possible cases now, problematic cases could be introduced in Mathematica X (where X > 7.01).

I fear that there cannot be a definitive answer to this problem until Wolfram introduces a new control structure expressly for this purpose. UnwindProtect would be a fine name for such a facility.

### Solution:3

Michael Pilat provided the key trick for "catching" returns, but I ended up using it in a slightly different way, using the fact that `Return` forces the return value of a named function as well as control structures like `Do`. I made the expression that is being cleaned up after into the down-value of a local symbol, like so:

``Attributes[CleanUp] = {HoldAll};  CleanUp[expr_, form_] :=    Module[{body, value, aborted = False},       body[] := expr;       Catch[      CheckAbort[       value = body[],       aborted = True];      form;      If[aborted,       Abort[],       value],      _, (form; Throw[##]) &]];  ``

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »