Надежная уборка в Mathematica

Что бы там ни было, Mathematica предлагает множество конструкций, которые позволяют вам осуществлять нелокальную передачу контроля, включаяReturn, Catch/Throw, Abort а такжеGoto, Однако такого рода нелокальные передачи управления часто вступают в конфликт с написанием надежных программ, которые должны обеспечивать выполнение кода очистки (например, закрытие потоков). Многие языки обеспечивают способы обеспечения выполнения кода очистки в самых разных ситуациях; У Java есть свояfinally блоки, C ++ имеет деструкторы, Common Lisp имеетUNWIND-PROTECT, и так далее.

В Mathematica я не знаю, как сделать то же самое. У меня есть частичное решение, которое выглядит так:

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

Это, конечно, не выиграет ни одного конкурса красоты, но это также только обрабатываетAbort а такжеThrow, В частности, он терпит неудачу при наличииReturn; Я полагаю, если вы используетеGoto чтобы сделать этот вид нелокального контроля в Mathematica, вы заслуживаете того, что получаете.

Я не вижу хорошего способа обойти это. Нет никакихCheckReturn например, и когда вы получите прямо к этому,Return имеет довольно темную семантику. Есть трюк, который я пропускаю?

РЕДАКТИРОВАТЬ: Проблема сReturnи неопределенность в его определении связана с его взаимодействием с условными выражениями (которые в Mathematica почему-то не являются «структурами управления»). Пример, используя мойCleanUp форма:

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

 Print["cleanup"]]

Это вернет «foo» без печати «cleanup». Точно так же,

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

 Print["cleanup"]]

вернет "связку" без очистки печати. Я не вижу пути обхода этого без утомительного, подверженного ошибкам и, возможно, невозможного обхода кода или какого-то локального переопределенияReturn с помощьюBlock, который ужасно хакерский и на самом деле не работает (хотя экспериментировать с ним - отличный способ полностью заклинить ядро!)

Ответы на вопрос(3)

Ваш ответ на вопрос