2011-10-27 1 views
12

Se valutiamo queste righe uno per uno, x verrà creato nel contesto cc.Perché questo uso di Begin [] non funziona?

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

Tuttavia, se li valutiamo insieme,

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

poi verrà creato in Globalx. Questo nonostante la stampa cc` quanto segue:

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

Qual è il motivo di questo comportamento? La mia ipotesi è che i contesti contano solo durante la fase di analisi, non di valutazione.

Caso di utilizzo: volevo creare una tavolozza Button che definirà alcuni simboli se non esistono ancora, in un contesto "privato" per evitare conflitti con i globali. Qual è il metodo preferito per fare questo, oltre a mettere tutte le definizioni in un file di pacchetto e caricarle dalla tavolozza? (Mi piacerebbe mantenere la tavolozza autonoma.)

+0

Ho appena letto in quella documentazione che "L'interpretazione dei nomi dei simboli dipende dal contesto' Begin' colpisce quindi il parsing di espressioni di input." Questo risponde alla mia prima domanda. Il secondo è ancora valido. – Szabolcs

risposta

15

I simboli (e i loro contesti) vengono creati durante l'analisi, non la valutazione. Se usiamo $NewSymbol possiamo vedere questo effetto:

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

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

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

I primi uno stampa:

first 
Name: test1 Context: Global` 
last 

perché ogni riga nella cella viene trattato come un ingresso separato. La seconda utilizza parentesi per forzare tutte le tre linee per essere considerato un ingresso e stampe

Name: test2 Context: Global` 
first 
last 

da cui possiamo vedere che test2 stata creata nel contesto Global` prima che si verificasse qualsiasi valutazione.

Penso che il modo più semplice per farlo è utilizzare un contesto esplicito sul proprio simbolo: cc`x = 1.

+0

+1, risultato interessante. – rcollyer

+3

Un'altra opzione a volte utile è utilizzare ToExpression per eseguire alcune nuove analisi * durante la valutazione *: (Begin ["cc'"]; Con [{s = ToExpression ["x"]}, s = 1]; End [ ];) –

+0

Brett, c'è un modo per usare '$ NewSymbol' per forzare la creazione di un simbolo in un contesto specifico, e per estensione non in quello predefinito? –

2

Per la seconda domanda, vi rimando alla risposta this, che automatizza in modo efficace i passaggi evidenziati (con la funzione ParseTimeNameSpaceWrapper). Potrebbe essere necessario più lavoro per renderlo più robusto, ma potrebbe essere un punto di partenza. Io uso questa roba me stesso in occasione.

+0

'ParseTimeNameSpaceWrapper' continua a non risolvere il fatto che il contesto dei simboli viene deciso in fase di analisi, ovvero se eseguo' ParseTimeNameSpaceWrapper [x] ', che' x' verrà comunque interpretato come '' Global'x' ', non come' 'MyLocalizedContext'x''. Dopo aver compreso che il contesto è stato scelto in fase di analisi, penso che non ci sia altro modo se non quello di forzare una ri-analisi inserendo del codice in una stringa e usando 'ToExpression', o leggendolo da un pacchetto (o semplicemente scrivendo il contesti esplicitamente come suggerisce Brett, ma è molto lavoro per codice più lungo). – Szabolcs

+0

@Szabolcs vedo. Forse questa discussione potrebbe interessarti, per quanto riguarda la fase di analisi: http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/c1f4ab24db8a8542 –

0

Solo per riferimento:

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

cc`x 
1