Module Mathematica versus avec ou Block-Guideline, règle empirique pour l'utilisation?

Leonid a écrit au chapitre iv de son livre:"... Module, bloc et avec. Ces constructions sont expliquées en détail dans Mathematica Book et Mathematica Help, donc je vais dire quelques mots à leur sujet ici. ..."

D'après ce que j'ai lu (j'ai pu trouver ) je suis toujours dans le noir. Pour les fonctions empaquetées, j'utilise (simplement ) le Module, car cela fonctionne et je connais la construction. Il peut ne pas être le meilleur choix si. Il n'est pas tout à fait clair pour moi ( à partir de la documentation ) quand, où ou pourquoi pour utilisation Avec ( ou Bloc ).

Question. Existe-t-il une règle empirique / directive sur l'utilisation du Module, avec ou Block ( pour les fonctions dans les paquets )? Y a-t-il des limitations par rapport au Module? Les docs disent Qu'avec est plus rapide. Je veux être capable de défendre mon = choix= pour le Module (ou une autre construction).

34
demandé sur nilo de roock 2011-07-12 12:27:16

4 réponses

Une différence plus pratique entre Block et Module peut être vue ici:

Module[{x}, x]
Block[{x}, x]
(*
-> x$1979
   x
*)

Donc, si vous souhaitez renvoyer par exemple x, vous pouvez utiliser Block. Par exemple,

Plot[D[Sin[x], x], {x, 0, 10}]

Ne fonctionne pas; pour le faire fonctionner, on peut utiliser

Plot[Block[{x}, D[Sin[x], x]], {x, 0, 10}]

(bien sûr, ce n'est pas l'idéal, c'est simplement un exemple).

Une autre utilisation est quelque chose comme Block[{$RecursionLimit = 1000},...], qui change Temporairement$RecursionLimit (Module n'aurait pas fonctionné car il renomme $RecursionLimit).

On peut aussi utiliser Block pour bloquer évaluation de quelque chose, par exemple

Block[{Sin}, Sin[.5]] // Trace
(*
-> {Block[{Sin},Sin[0.5]],Sin[0.5],0.479426}
*)

C'est-à-dire qu'il renvoie Sin[0.5] qui n'est évalué qu'après la fin de l'exécution de Block. C'est parce que Sin dans Block est juste un symbole, plutôt que la fonction sinus. Vous pourriez même faire quelque chose comme

Block[{Sin = Cos[#/4] &}, Sin[Pi]]
(*
-> 1/Sqrt[2]
*)

(utilisez Trace pour voir comment cela fonctionne). Vous pouvez donc utiliser Block pour redéfinir localement les fonctions intégrées:

Block[{Plus = Times}, 3 + 2]
(*
-> 6
*)
28
répondu acl 2011-07-12 11:46:48

Comme vous l'avez mentionné, il y a beaucoup de choses à considérer et une discussion détaillée est possible. Mais voici quelques règles de base que j'applique la majorité du temps:

Module[{x}, ...] est le plus sûr et peut être nécessaire si

  1. Il existe des définitions existantes pour x que vous voulez éviter de casser lors de l'évaluation du Module, ou

  2. Il existe un code existant qui repose sur x undefined (par exemple un code comme Integrate[..., x]).

Le Module est également le seul choix pour créer et renvoyer un nouveau symbole. En particulier, le Module est parfois nécessaire dans la programmation dynamique avancée pour cette raison.

Si vous êtes sûr qu'il n'y a pas de définitions existantes importantes pour x ou tout code qui repose sur le fait qu'il n'est pas défini, alors Block[{x}, ...] est souvent plus rapide. (Notez que, dans un projet entièrement codé par vous, être sûr de ces conditions est une norme "d'encapsulation" raisonnable que vous pouvez souhaiter appliquer de toute façon, et donc bloquer est souvent un choix judicieux dans ces situations.)

With[{x = ...}, expr] est la seule construction de portée qui injecte la valeur de x à l'intérieur de Hold[...]. Ceci est utile et important. With peut être plus rapide ou plus lent que le bloc en fonction de expr et du chemin d'évaluation particulier qui est pris. With est cependant moins flexible, car vous ne pouvez pas changer la définition de x dans expr.

29
répondu Andrew Moylan 2011-07-12 11:46:49

Andrew a déjà fourni une réponse très complète. Je résumerais simplement en notant que {[1] } sert à définir des variables locales qui peuvent être redéfinies dans le cadre d'une définition de fonction, tandis que With sert à définir des constantes locales , ce qui ne peut pas l'être. Vous ne pouvez pas non plus définir une constante locale en fonction de la définition d'une autre constante locale que vous avez définie dans la même instruction With, ou avoir plusieurs symboles sur le LHS d'une définition. Qui est, le la suite ne fonctionne pas.

With[{{a,b}= OptionValue /@ {opt1,opt2} }, ...]

J'ai tendance à mettre en place des définitions de fonctions compliquées avec Module englobant un With. J'ai mis en place toutes les constantes locales que je peux d'abord dans le With, par exemple le Length des données transmises à la fonction, si j'en ai besoin, puis d'autres variables locales au besoin. La raison en est que With est un peu plus rapide d'avoir vraiment des constantes pas des variables.

9
répondu Verbeia 2011-07-12 13:44:32

Je tiens à mentionner la documentation officielle sur la différence entre Block et Module est disponible à http://reference.wolfram.com/mathematica/tutorial/BlocksComparedWithModules.html.

9
répondu Meng Lu 2011-07-13 17:14:42