2010-03-22 9 views
4

Ma question est: pourquoi ce qui suit ne fonctionne pas, et comment puis-je le réparer?Comportement bizarre de substitution dans Mathematica

Plot[f[t], {t, 0, 2*Pi}] /. {{f -> Sin}, {f -> Cos}} 

Le résultat est deux graphes vierges. Par comparaison,

DummyFunction[f[t], {t, 0, 2*Pi}] /. {{f -> Sin}, {f -> Cos}} 

donne

{DummyFunction[Sin[t], {t, 0, 2 *Pi}], DummyFunction[Cos[t], {t, 0, 2 * Pi}]} 

comme vous le souhaitez.

Ceci est une version simplifiée de ce que je faisais réellement. J'ai été très ennuyé que, même après avoir compris la «bonne façon» de mettre les accolades ne fonctionne rien.

En fin de compte, je l'ai fait ce qui suit, qui fonctionne:

p[f_] := Plot[f[t], {t, 0, 2*Pi}] 
p[Sin] 
p[Cos] 

Répondre

4

Mathematica tente d'évaluer terrain avant la substitution. Vous pouvez empêcher que les fonctions HOLD et ReleaseHold:

ReleaseHold[Hold[Plot[f[t],{t,0,2*Pi}]] /. {{f -> Sin},{f -> Cos}}] 

Maintenez la touche [] forcera l'ensemble de la parcelle de rester sous-expression non simplifiée tandis que la substitution est effectuée, puis ReleaseHold [] laissera-t-il procéder à la réelle tracé.

+0

Merci pour votre réponse. Votre solution a une faute de frappe, vous devriez avoir /. au lieu du premier ->. Ça marche. Cependant, cela n'a pas beaucoup de sens pour moi que la substitution ne soit pas en haut de l'ordre de préséance ... – Ilya

+0

(La faute de frappe est maintenant fixée par Ramasalanka) – Ilya

+0

Je ne peux pas expliquer pourquoi l'ordre des opérations est la manière est, mais ce n'est pas juste complot. Mathematica essayera d'évaluer n'importe quelle fonction du côté gauche de /. (désolé de la faute de frappe plus tôt) avant qu'il effectue la substitution. Une grande partie du temps n'a pas d'importance: le f [t] non défini sera simplement transmis à travers la définition de la fonction jusqu'à ce que la substitution soit effectuée. Par exemple, myFun [x_, l_]: = x/@ l; myFun [f, {1,2,3}] /. {{f-> Sin}, {f-> Cos}} fonctionnera comme vous le souhaitez. Mais Plot [] est l'un des exemples où avoir f [t] indéfini entraînera une erreur immédiate. –

7

Comme alternative à la stratégie de Peter Hold/ReleaseHold vous pouvez faire

Plot[Evaluate[ f[t]/. {{f -> Sin}, {f -> Cos}} ], {t, 0, 2*Pi}] 

qui est un peu plus propre à lire. Ceci assure que f est substitué avant que Plot soit évalué.

+0

Vous ne même pas besoin de la 'évaluer []', juste après avoir déplacé le la substitution à l'intérieur de 'Plot []' est suffisante. 'Tracer [f [t] /. {{f -> Sin}, {f -> Cos}}, {t, 0, 2 * Pi}] ' – Isaac

+0

@Isaac: Pas toujours. Il y a eu des fois où j'ai trouvé qu'il est nécessaire d '"évaluer" en premier, sinon "Tracer" ne fait pas ce que vous attendez. – rcollyer

+0

@rcollyer: Oui, cela dépend de ce qui est substitué.Dans ce cas particulier, cela fonctionne comme je l'ai dit, cependant (au moins pour moi dans 7.0.1.0) votre code produit les courbes dans deux couleurs différentes et mon code produit les deux courbes dans la même couleur. Bien sûr, votre code et le mien produisent deux courbes sur une grille, ce qui n'était peut-être pas ce que l'affiche originale voulait (peut-être deux grilles séparées). – Isaac

7

Celui-ci est encore plus courte:

Plot[#[t], {t, 0, 2*Pi}] & /@ {Sin, Cos} 
+0

C'est très bien! J'accepte la réponse de Peter car elle ressemble moins à un puzzle, mais c'est certainement un moyen cool de raccourcir ma "solution" à une ligne. – Ilya

+0

Pour continuer à faire du lobbying pour cette méthode (et Peter peut être étendu de la même manière), ceci peut être étendu en utilisant MapIndexed ou MapThread pour vous permettre de styliser chaque tracé différemment. De plus, ils peuvent ensuite être combinés en utilisant 'Show' pour créer des tracés plutôt complexes. (C'est la méthode que j'ai tendance à privilégier dans mon analyse de données.) – rcollyer