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).
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
*)
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
-
Il existe des définitions existantes pour x que vous voulez éviter de casser lors de l'évaluation du Module, ou
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.
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.
Je tiens à mentionner la documentation officielle sur la différence entre Block
et Module
est disponible à http://reference.wolfram.com/mathematica/tutorial/BlocksComparedWithModules.html.