2013-07-02 21 views
8

Let Over Lambda Chapter 3 Section 'Unwanted Capture' mówi:..Co może pójść nie tak, kiedy definiuję makro i po prostu używam wystarczająco rzadkiej nazwy dla zmiennej tymczasowej?

„Na pewno możemy myśleć o tyle rzadkich imion tak, że problem nie pokazuje się tak, w wielu przypadkach, pakietów i inteligentnego zmiennego nazewnictwa może rozwiązać problem zmiennej wychwytywania Jednak najpoważniejszym zmienna wychwytywania błędów nie wynikają bezpośrednio w kodzie stworzony przez programistę. Większość problemów zmienna przechwytywania powierzchniowe tylko gdy inne makra użyć makra (połączyć ze swoją makro) w taki sposób, że nie przewidujemy. "

a następnie nie daje mi przykładu na odważną część. Jaki byłby jeden z takich przykładów? Wyobraź sobie hipotetyczny zespół Lisp dev, w którym jego szalony szef zakazał używania gensymu lub czegokolwiek, co tworzy niezamieszkane symbole, a programiści po prostu uciekają się do rzucania alfanumerycznymi kostkami, aby wymyślić losowe nazwy zmiennych, takie jak temp-27s63f8sk2n lub sum-3t84hj4df za każdym razem, gdy tęsknią za gensym. Jaki byłby przykład, kiedy drużyna będzie miała kłopoty?

Mówiąc o tym, Emacs 24.3.1 definiuje kropki i dolistkę bez użycia nieopisanych symboli. Dziwne.

+6

Dlaczego ludzie decydują się na zamknięcie tego? To prawdziwe i złożone pytanie. – d11wtq

Odpowiedz

1

Problem pojawia się, gdy ponownie używasz własnego makra w innym kontekście, a sprytnie zmienne ze spacjami są efektywnie wtedy zbędne, ponieważ wszystkie są w tej samej przestrzeni nazw.

mogę myśleć przykład będącego przy użyciu zamknięcie, które uzyskuje dostęp do zmiennej w otaczającej (let), lecz przeszedł do makra, które również wykorzystuje się otaczającą (let) definiowania zmiennej „bezpieczne” z nazwą starcia. To wymyślny przykład, przepraszam, nie mogę teraz myśleć o prawdziwym świecie.

(defmacro my/a (x) 
    (let ((my/safe-name x)) 
    `(progn ,(my/b (lambda() my/safe-name)) 
      ,my/safe-name))) 

(defmacro my/b (f) 
    `(let ((my/safe-name 4)) 
    (when (evenp (funcall ,f)) 
     (print "F is even!")))) 

(my/a 3) ; will print "F is even", but it shouldn't 
+0

Zwykły zespół programistów napisze to z * dwoma * połączeniami gensym lub wywołaniami symboli make. Hipotetyczny zespół deweloperów uruchomi dwa razy * swój pseudolosowy alfalfumeryczny generator postfiksów *. Tak będzie (mój/safe-name-6kuyd4kq x)) w moim/a i ((my/safe-name-pqedzkwg 4)) w moim/b. Aby ten zespół miał kłopoty, potrzebowalibyśmy kodu, który rozszerzyłby się do kodu, który w jakiś sposób podniósłby moje/safe-name-6kuyd4kq i sprawił, że w jakiś sposób kolidowałby ze sobą. Podejrzewam, że o to chodzi w tej odważnej części, ale brakuje jej przykładu, więc nie jestem pewien. –

+0

Używanie gensym jest dokładnie tym, co Doug Hoyte sugeruje jako rozwiązanie niepożądanego przechwytywania. Masz problemy tylko wtedy, gdy zaniedbujesz korzystanie z gensymów. Właśnie to Hoyte próbuje powiedzieć. W tym momencie książki zakłada, że ​​jeszcze nie wiesz o gensymach, tylko wybrane nazwy zmiennych (ale nazwane spacjami). – d11wtq

2

OK, to proponuję zautomatyzować proces "rzucania kostkami alfanumerycznymi". Oczywiście nie musi to być losowe, wystarczy użyć licznika. Dodatkowo byłoby miło móc określić prefiks do debugowania. Och, czekaj, to jest dokładnie to, co robi gensym.

+0

Gensym zwraca niezamocowane symbole. Hipotetyczny zespół używa tylko symboli INTERNED. Jeśli zespół opiera się na 'intern-gensym', który jest jak' gensym', ale zwraca internowane symbole, wtedy wpadną w tarapaty, ponieważ imiona G10, G11, G12 .... nie są rzadkością i istnieje szansa, że ​​użytkownicy makr będą używać takich nazw zmiennych, a taki przykład jest podany w połączonym artykule Let Over Lambda. –

+0

Jeśli zespół używa internowanych symboli z przypadkowym postfiksem, można uniknąć problemów z tego przykładu. Następnie artykuł mówi, że istnieje jeszcze inny sposób wpadnięcia w kłopoty, odważna część cytatu. Czy odważna część może sprawić, że zespół będzie miał kłopoty? –