Odpowiedz

3

Cóż, jest kilka stron internetowych, które omawiają pro i con, więc nie zamierzam tam być.

Jednym z interesujących języków, który ma pewne cechy, które słabo przypominają zakres dynamiczny, jest XSLT; chociaż szablony i zmienne XSLT i podobne mają zakres leksykalny, XSLT dotyczy oczywiście XML - a aktualna pozycja w drzewie xml jest "dynamicznie określana" w tym sensie, że węzeł kontekstu jest globalny, a zatem wyrażenia XPath są oceniane nie zgodnie z leksykalnym zakresem XSLT, ale według jego dynamicznej oceny.

7

Mathematica jest innym językiem, który jest dynamicznie określany przez konstrukcję Block. Jest to całkiem przydatne podczas pracy z formułami. To pozwala na pisanie rzeczy jak

In[1]:= expr = a*t^2 + b*t+ c; 

In[2]:= Block[{a = 1, b = -1, c = 2}, Table[expr, {t, 5}]] 
Out[2]= {2, 4, 8, 14, 22} 

które nie działają w ogóle, jeśli zmienne jak a i t zostały zawężona leksykalnie. Szczególnie dobrze współpracuje z systemem przepisywania reguł przez Mathematica, który, między innymi, pozostawi zmienne niedoszacowane (jako wyrażenia symboliczne), jeśli nie ma dla nich istniejącej definicji.

Mathematica może wymyślać zakres leksykalny za pomocą konstrukcji Module, ale tak naprawdę to jest przepisanie wyrażenia w kategoriach nowego, rzekomo unikatowego symbolu (możesz przewidzieć konflikty, jeśli przewidujesz, jaki będzie kolejny unikalny symbol, co jest łatwe w większości przypadków). Oznacza to

Module[{x = 4}, 
    Table[x * t, {t, 5}]] 

zostanie przekształcony w coś takiego:

Block[{x$134 = 4}, 
    Table[x$134 * t, {t, 5}] 

Emacs Lisp, w jednym ze swoich bibliotek, ma konstrukcję (naprawdę Lisp makro) o nazwie lexical-let że wciąga dokładnie tę samą sztuczkę do sfałszowania zakresu leksykalnego.

Istnieją pewne zalety związane z wydajnością w zakresie rzeczywistego zakresu leksykalnego podczas kompilacji języka, którego nie można uzyskać za pomocą fałszywych leksykalnych ELisp lub Mathematica, ponieważ potrzebne jest pewne odwzorowanie między zmienną dynamiczną a jej bieżącą wartością, co oznacza, że wykonywanie odnośników (poprzez tablicę asocjacyjną lub listę właściwości lub coś takiego) i dodatkowe warstwy pośrednie.

EDIT: Jeśli masz tylko zmienne leksykalne, można fałszywe dynamiczna analiza zakresu przechowując oryginalną wartość zmiennej leksykalnej, globalnej po wejściu do zakresu i zagwarantowania, że ​​stara wartość zostanie przywrócony po opuszczeniu zakresu. Aby to zapewnić, będziesz potrzebował czegoś podobnego do bloku Lisp: UNWIND-PROTECT lub finally. Widziałem to również przy użyciu destruktorów C++, głównie jako ćwiczenia.

9

Dynamicznie stosowane języki są znacznie łatwiejsze do wdrożenia. Aby uzyskać dostęp do zmiennych, które nie znajdują się w bieżącym rekordzie aktywacji/stosie, można po prostu podążać za łączami sterującymi. Statyczne/leksykalne łącza dostępu nie są wtedy potrzebne, co powoduje, że ramki stosu są mniejsze.

Zmienne dynamiczne mogą być "nieprzewidywalne" w czasie wykonywania, ponieważ trzeba wiedzieć, w jakiej kolejności rzeczywiste ramki stosu mają wiedzieć, która zmienna zostanie użyta. Ta informacja nie jest dostępna po prostu patrząc na statyczną strukturę kodu. Można dość łatwo złapać, jeśli rzeczywisty wykres połączeń programu nie jest łatwy do przewidzenia w czasie wdrażania.Dlatego większość dzisiejszych języków ma statyczne scoping (większość systemów Exception jest jednak dynamiczna, ponieważ jest to najbardziej praktyczne).

Jednak w niektórych przypadkach bardzo przydatne są zmienne o dynamicznym zakresie. Na przykład podczas przekierowywania danych wyjściowych można użyć zmiennych dynamicznych ustawić standardowe wyjście dla kodu lokalnego i cały kod wywoływany z tego miejsca.

(let ((*standard-output* *some-other-stream*)) 
(stuff)) 

W tym wspólnym seplenienie przykład (z Seibel), moc średnia jest związany z innym strumieniem w czasie trwania postaci Pozwolić (wewnątrz jego zamykających parens). Kiedy egzekucja opuszcza let, wraca do tego, co było wcześniej. Zobacz http://gigamonkeys.com/book/variables.html Peter Seibels darmową i świetną książkę, Practical Common Lisp, na dobrą dyskusję. W języku Seibels własne słowa:

Wiązania dynamiczne sprawiają, że zmienne globalne są dużo łatwiejsze w zarządzaniu, ale ważne jest, aby zauważyć, że nadal pozwalają na działanie na odległość. Wiązanie zmiennej globalnej ma dwa efekty na odległość - może zmienić zachowanie kodu niższego rzędu, a także otwiera możliwość, że niższy kod przydzieli nową wartość powiązaniu ustalonemu wyżej na stosie. Zmiennych dynamicznych należy używać tylko wtedy, gdy trzeba skorzystać z jednej lub obu tych cech.

3

Zakres dynamiczny jest/był łatwiejszy do wdrożenia z tłumaczami. Większość wczesnych tłumaczy Lisp używało zakresu dynamicznego. Po kilku latach zasięg leksykalny miał przewagę, ale najpierw został zaimplementowany głównie w kompilatorach Lisp. Pojawiło się kilka implementacji, które zaimplementowały zakres dynamiczny w zinterpretowanym kodzie i zakresie leksykalnym w skompilowanym kodzie. Niektórzy dostarczyli specjalne konstrukcje językowe, aby zapewnić zamknięcia. Językowe dialekty Lispa, takie jak Scheme i Common Lisp, wymagały wówczas, aby nie było żadnej różnicy między interpretowanym i skompilowanym kodem, a zatem implementacje oparte na interpretacji musiały również implementować zakres leksykalny.

Implementacje Early Smalltalk zaimplementowały zakres dynamiczny. Wszystkie rodzaje implementacji dialektów Lisp zaimplementowały zakres dynamiczny (Interlisp, UCI Lisp, Lisp Machine Lisp, MacLisp, ...).

Prawie wszystkie nowe dialekty Lispa z ostatnich 20 lat domyślnie lub nawet wyłącznie korzystają z zakresu leksykalnego. Kilka publikacji opisało szczegółowo, w jaki sposób wdrożyć Lisp w zakresie leksykalnym - więc nie ma wymówki, by nie używać zakresu leksykalnego.

2

Wszystkie języki powłoki (bash, ksh, itp.) Używają dynamicznego zakresu.

Powiązane problemy