2011-10-27 9 views
12

Jeśli ocenimy te linie: jeden po drugim, x zostanie utworzony w kontekście cc.Dlaczego to używanie funkcji Begin [] nie działa?

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

Jednakże, jeśli je oceniać razem,

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

następnie x zostanie utworzony w Global. Dzieje się tak pomimo poniższych drukowania cc`:

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

Co jest przyczyną takiego zachowania? Zgaduję, że konteksty mają znaczenie tylko podczas fazy analizy, a nie oceny.

Przypadek użycia: Chciałem utworzyć paletę Button, która zdefiniuje niektóre symbole, jeśli jeszcze nie istnieją, w "prywatnym" kontekście, aby uniknąć konfliktu z globalnymi. Jaka jest preferowana metoda wykonywania tego, inne niż umieszczanie wszystkich definicji w pliku pakietu i ładowanie ich z palety? (Chciałbym zachować niezależność palety).

+0

Właśnie przeczytałem, że w Dokumentach, że „Interpretacja nazw symboli zależy od kontekstu' Begin' wpływa więc parsowanie wyrażeń wejściowych.” To odpowiada na moje pierwsze pytanie. Drugi wciąż stoi. – Szabolcs

Odpowiedz

15

Symbole (i ich konteksty) są tworzone podczas analizy, a nie podczas oceniania. Jeśli używamy $NewSymbol widzimy to w rezultacie:

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

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

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

pierwszy wydruki:

first 
Name: test1 Context: Global` 
last 

ponieważ każda linia w komórce jest traktowany jako oddzielny wejścia. Drugi wykorzystuje nawiasy zmusić wszystkich trzech linii uznać jedno wejście i drukuje

Name: test2 Context: Global` 
first 
last 

, z którego widać, że test2 powstała w kontekście Global` przed wystąpieniem dowolnego oceny.

Myślę, że najprościej z tym pracować, używając wyraźnego kontekstu na swoim symbolu: cc`x = 1.

+0

+1, ciekawy wynik. – rcollyer

+3

Inną opcją, która czasami jest przydatna, jest użycie funkcji ToExpression w celu wykonania nowej analizy podczas * oceny: (Rozpocznij ["cc" "]; [[s = ToExpression [" x "]}, s = 1]; Koniec [ ];) –

+0

Brett, czy istnieje jakikolwiek sposób użycia '$ NewSymbol' do wymuszenia utworzenia symbolu w określonym kontekście, a przez rozszerzenie nie w domyślnym? –

2

Dla twojego drugiego pytania, odsyłam do mojej odpowiedzi this, która skutecznie automatyzuje kroki, które opisałeś (z funkcją ParseTimeNameSpaceWrapper). Może wymagać więcej pracy, aby uczynić go solidniejszym, ale może to być punkt wyjścia. Używam tych rzeczy osobiście przy okazji.

+0

'ParseTimeNameSpaceWrapper' nadal nie omija faktu, że kontekst symboli jest ustalany w czasie parsetu, tzn. Jeśli robię' ParseTimeNameSpaceWrapper [x] ', to' x' będzie nadal interpretowane jako '' Global'x' ', a nie jako' 'MyLocalizedContext'x''. Po zrozumieniu, że kontekst jest wybierany w czasie parse, myślę, że nie ma innego sposobu, jak tylko wymusić ponowne przeanalizowanie przez umieszczenie jakiegoś kodu w ciągu i użycie 'ToExpression' lub odczytanie go z paczki (lub po prostu napisanie konteksty jawnie, jak sugeruje Brett, ale to dużo pracy dla dłuższego kodu). – Szabolcs

+0

@Szabolcs Widzę. Być może ten wątek może Cię zainteresować, jeśli chodzi o etap analizy: http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/c1f4ab24db8a8542 –

0

Tylko dla odniesienia:

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

cc`x 
1 
Powiązane problemy