2010-06-05 16 views
8

Moje ręce były mokre z empsem seplenieniem, a jedną rzeczą, która mnie czasami wyzwala, jest zasięg dynamiczny. Czy jest na to wiele przyszłości? Większość znanych mi języków używa statycznego zakresu (lub przeniosłem się do statycznego określania zakresu, np. Python), i prawdopodobnie dlatego, że wiem, że jestem lepszy, preferuję go. Czy istnieją konkretne aplikacje/instancje lub przykłady, w których zakres dynamiczny jest bardziej przydatny?wykorzystuje zakres dynamiczny?

+2

Wiele [użytecznych odpowiedzi tutaj] (http://stackoverflow.com/questions/321000/dynamic-scoping-why) - być może jest to wystarczająco blisko, aby być duplikatem? –

+0

Tak, wygląda na to. Mój błąd. – hatmatrix

Odpowiedz

14

Istnieje dobra dyskusja na ten temat here. Najbardziej przydatna część dotycząca Twojego pytania to:

Wiązania dynamiczne są świetne dla modyfikując zachowanie podsystemów. Załóżmy, że używasz funkcji "foo" , która generuje dane wyjściowe za pomocą "print". Ale czasami chcesz uchwycić wyjście w buforze swojego wyboru . Z dynamicznym wiązaniu, to proste:

(let ((b (generate-new-buffer-name " *string-output*")))) 
    (let ((standard-output b)) 
     (foo)) 
    (set-buffer b) 
    ;; do stuff with the output of foo 
    (kill-buffer b)) 

(A jeśli użyto tego typu rzeczy się dużo, można by ująć go w makro - ale na szczęście to już zostało zrobione jak „z-wyjścia do temp-bufora”).

To działa, ponieważ „foo” używa dynamiczne wiązanie nazwy „norma-odbiorczego”, więc można zastąpić własne wiążące dla t hat nazwa, aby zmodyfikować zachowanie 'foo' - oraz wszystkich funkcji, które wywołują "foo" .

W języku bez dynamicznego wiązania ty pewnie dodać opcjonalny argument „foo”, aby określić bufor a następnie „foo” minie, że do żadnej wywołań „Print”. Ale jeśli 'foo' dzwoni inne funkcje, które same nazywają się 'print', będziesz musiał również zmienić te funkcje . A jeśli "print" miałby inną opcję, powiedzmy "poziom wydruku", , musiałbyś dodać to jako opcjonalny argument również ... Alternatywnie, możesz może zapamiętać starą wartość "standardowe wyjście", Zastąp swoją nową wartość , wywołaj "foo", a następnie przywróć starą wartość . I pamiętaj, aby obsługiwać nie-lokalne wyjścia z wykorzystaniem "rzutu". Po wykonaniu tej czynności zobaczysz , że zaimplementowano dynamiczne wiązanie !

To powiedziane, leksykalne wiązanie jest IMHO znacznie lepsze dla 99% przypadków. Zauważ, że nowoczesne Lisps nie są wiążące dynamicznie, jak np. Empers Empsa.

  • Common Lisp obsługuje obie formy wiązania, chociaż jeden leksykalny jest używany znacznie więcej
  • specyfikację programu nawet nie określił dynamicznego wiązania (tylko jeden leksykalne), choć wiele implementacji wspierać oba.

Ponadto, współczesne języki, takie jak Python i Ruby, które były w pewien sposób inspirowane przez Lispa, zwykle wspierają leksykalne powiązanie w prosty sposób, z dynamicznym wiązaniem również dostępnym, ale mniej prostym.

7

Po przeczytaniu Emacs paper (napisanej w 1981 r.) Istnieje specjalna sekcja "Language Features for Extensibility", która rozwiązuje ten problem. W Emacsie jest także dodany zakres zmiennych lokalnych dla bufora (plik lokalny).

mam cytowany najodpowiedniejszym część poniżej:

Formal Parameters Cannot Replace Dynamic Scope

Niektórzy projektanci uważają, że język dynamiczne wiązanie powinno się unikać, a wyraźne odejście argument powinien być stosowany zamiast . Wyobraź sobie, że funkcja A wiąże zmienną FOO, i wywołuje funkcję B, która wywołuje funkcję C, a C używa wartości FOO. podobno powinien przekazać wartość jako argument do B, który powinien przekazać go jako argument do C.

ta nie może być wykonana w systemie rozszerzalny jednak, ponieważ autor system nie może wiedzieć jakie będą wszystkie parametry . Wyobraź sobie, że funkcje A i C są częścią rozszerzenia użytkownika , natomiast B jest częścią standardowego systemu . Zmienna FOO ma nie istnieje w standardowym systemie; to jest częścią rozszerzenia. Aby korzystać wyraźne odejście argumentu byłoby wymagają dodając nowy argument do B, co oznacza, przepisywanie B i wszystko który wywołuje B. W najczęstszym przypadku B jest polecenie Edytor dyspozytor pętla, która jest wywoływana z straszne Liczba miejsc.

Co gorsza, C musi również zostać przesłany dodatkowy argument. B nie odsyła do C przez nazwę (C nie istniało, gdy napisano B ). Prawdopodobnie znajdzie wskaźnik do C w tabeli rozkazów komend . Oznacza to, że to samo wywołanie , które czasami wywołuje C, może równie dobrze wywoływać dowolną definicję edytora o wartości . Dlatego wszystkie polecenia edycji muszą zostać przepisane, aby zaakceptować i zignorować dodatkowy argument. Od teraz żaden z oryginalnych systemów nie jest już dostępny!

+0

Doskonała oferta! Jest to naprawdę doskonały przykład przydatności wiązania dynamicznego. Dzięki za udostępnienie! –

+0

Dziękuję - bardzo ilustracyjny – hatmatrix

Powiązane problemy