Waarom werkt dit gebruik van Begin [] niet?

Als we deze regels evalueren, wordt één voor één , x gemaakt in de context cc .

Begin["cc`"];
x = 1;
End[]

Als we ze echter samen evalueren,

(Begin["cc`"];
x = 1;
End[])

dan wordt x aangemaakt in Globaal . Dit is ondanks het volgende printen cc` :

(Begin["cc`"];
Print[$Context];
End[])

What is the reason for this behaviour? My guess is that contexts only matter during the parsing phase, not evaluation.

Use case: ik wilde een palet maken Knop die sommige symbolen zal definiëren als ze nog niet bestaan, in een "private" context om conflicten met globalen te voorkomen. Wat is de voorkeursmethode om dit te doen , behalve alle definities in een pakketbestand te plaatsen en ze vanuit het palet te laden? (Ik wil het palet op zichzelf houden.)

12
Ik heb zojuist in die documenten gelezen dat "de interpretatie van symboolnamen afhankelijk is van context. Begin beïnvloedt dus het parseren van invoer-expressies." Dat beantwoordt mijn eerste vraag. De tweede staat nog steeds.
toegevoegd de auteur Szabolcs, de bron

3 antwoord

Symbolen (en hun contexten) worden gemaakt tijdens het parseren, niet voor de evaluatie. Als we $ NewSymbol gebruiken, kunnen we dit zien:

$NewSymbol=Print["Name: ",#1," Context: ",#2]&

Print["first"];
test1;
Print["last"]

(Print["first"];
 test2;
 Print["last"])

De eerste print:

first
Name: test1 Context: Global`
last

omdat elke regel in de cel wordt behandeld als een afzonderlijke invoer. De tweede gebruikt haakjes om alle drie de regels als één invoer te beschouwen en af ​​te drukken

Name: test2 Context: Global`
first
last

van waaruit we kunnen zien dat test2 is gemaakt in de context Globaal voordat er een evaluatie plaatsvond.

Ik denk dat de eenvoudigste manier om hiermee te werken, is door een expliciete context op je symbool te gebruiken: cc`x = 1 .

15
toegevoegd
@ Mr.Wizard waarschijnlijk niet, omdat $ NewSymbol geen invloed heeft op wat er met dat symbool gebeurt tijdens verdere evaluatie. Ik deed iets om hetzelfde te doen als wat @Andrew zei. Wanneer het gebruik van expliciete contextnamen omslachtig wordt, kan men alles in een .m-bestand plaatsen en dat lezen. De manier om het palet onafhankelijk te maken, is misschien om een ​​enorm string in plaats van een .m-bestand te gebruiken en daaruit te lezen. Tenzij is er misschien een betrouwbare notebook/front-end wizard om de code op te nemen in de paletkladblok en de definities te evalueren wanneer het palet is geladen.
toegevoegd de auteur Szabolcs, de bron
@ Mr. Wizard Ik denk dat dit een aparte vraag verdient. Ik heb niet veel ervaring met de notebook en de voorkant.
toegevoegd de auteur Szabolcs, de bron
Brett, is er een manier om $ NewSymbol te gebruiken om een ​​symbool te dwingen om in een specifieke context te worden gemaakt, en bij uitbreiding niet in de standaardcontext?
toegevoegd de auteur Mr.Wizard, de bron
@Andrew, waarom plaats je dit niet als een antwoord?
toegevoegd de auteur Mr.Wizard, de bron
@Szabolcs is eigenlijk al gevraagd, maar het is nooit opgelost. Zie: stackoverflow.com/questions/6167406/ & hellip;
toegevoegd de auteur Mr.Wizard, de bron
Bedankt Brett, net aan het checken.
toegevoegd de auteur Mr.Wizard, de bron
+1, interessant resultaat.
toegevoegd de auteur rcollyer, de bron
@ Mr.Wizard Ik denk dat het duidelijk is uit het documentatiemodel voor $ Nieuwe symbolen met behulp van Afdrukken dat de uitvoer van de functie niet wordt gebruikt voor het maken van het nieuwe symbool (anders zijn alle nieuwe symbolen zijn Null .)
toegevoegd de auteur Brett Champion, de bron
Een andere optie die soms handig is, is ToExpression te gebruiken om wat nieuw te ontleden tijdens evaluatie: (Begin ["cc`"]; Met [{s = ToExpression ["x"]}, s = 1 ]; Einde [];)
toegevoegd de auteur Andrew Moylan, de bron

Voor uw tweede vraag verwijs ik u naar dit antwoord van mine, die op effectieve wijze de stappen automatiseert die u hebt beschreven (met de functie ParseTimeNameSpaceWrapper ). Het kan meer werk vergen om het robuuster te maken, maar dat kan een beginpunt zijn. Ik gebruik dit spul soms bij gelegenheid.

2
toegevoegd
ParseTimeNameSpaceWrapper komt er nog steeds niet tussenuit dat de context van symbolen wordt bepaald op parse-time, maw als ik ParseTimeNameSpaceWrapper [x] , die x zal nog steeds worden geïnterpreteerd als Global`x , niet als MyLocalizedContext`x . Nadat ik heb begrepen dat de context is gekozen in parse-time, denk ik dat er geen andere manier is dan een herverzending te forceren door een code in een string te plaatsen en ToExpression te gebruiken, of door het uit een pakket te lezen (of gewoon de contexten expliciet schrijven zoals Brett suggereert, maar dat is veel werk voor langere code).
toegevoegd de auteur Szabolcs, de bron
@Szabolcs zie ik. Misschien is deze thread misschien interessant voor u, met betrekking tot de parseerfase: groups.google.com/group/comp.soft-sys.math.mathematica/& hellip;
toegevoegd de auteur Leonid Shifrin, de bron

Gewoon voor referentie:

(Begin["cc`"]; Evaluate[Symbol["x"]] = 1; End[])

cc`x
  1
 
0
toegevoegd