2012-12-25 20 views
6

Czy istnieje sposób oznaczenia symbolu jako przestarzały w Clojure?Przestarzałe symbole w Clojure

Mogę użyć czegoś takiego z Lein, który działa dobrze.

https://github.com/technomancy/leiningen/blob/1.x/src/leiningen/core.clj#L13

Ale to emituje tylko jego ostrzeżenie, gdy funkcja jest wywoływana. Naprawdę chciałbym, aby kompilator wybrał to w czasie kompilacji kodu, a nie po jego wywołaniu.

Oczywiście, mogę tylko nie określenie symbolu, który kompilator by następnie odebrać , ale to pozbawia mnie o zdolność do dostarczenia wszelkich informacji, takich jak, dlaczego, lub gdy symbol została zaniechana .

Wszystko to dotyczy DSL, gdzie deprecjacja i starzenie się terminów ma nastąpić w rozsądnym tempie.

+1

Zamiast przedefiniować funkcję jako inną funkcję, zdefiniuj ją ponownie jako makro, które emituje ostrzeżenie podczas rozszerzania w czasie kompilacji. – Barmar

+0

@Barmar Co uniemożliwia użycie jako argumentu lub dosłownie. Okropny pomysł. Zamiast tego, po prostu wymuś ostrzeżenie podczas rozszerzania defdeprobowanego makra. (Co oczywiście oznacza, że ​​ostrzeżenie pojawia się tylko podczas kompilacji biblioteki, co może nie być tym, czego potrzebujesz). – Cubic

+0

@cubic Nie, to też jest złe. Chodzi o to, aby ostrzec, gdy aplikacja klienta przestaje być przestarzałą funkcją, a nie kiedy biblioteka jest kompilowana. Myślę, że uzyskanie tego, co naprawdę potrzebne, wymaga szczególnego wsparcia w kompilatorze Clojure. – Barmar

Odpowiedz

1

Jest już coś w komentarzach na temat używania makr, ale jak ktoś zauważył, wyklucza to użycie funkcji jako HOF. Możesz obejść to, chociaż może się okazać, że lekarstwo nie jest gorsze od choroby. Na przykład, wyobraź sobie swoją funkcją jest

(defn foo* [x y] (+ x y)) 

Wtedy zamiast pisać

(defmacro foo [x y] (warn) `(foo* x y)) 
(foo 1 2) 
(map foo [5 6] [7 8]) 

Można uczynić macroexpansion cofnięcie funkcję, co oczywiście może być używany jak każdy inny:

(defmacro foo [] (warn) `foo*) 
((foo) 1 2) 
(map (foo) [5 6] [7 8]) 

Prawdopodobnie nie jest to warte niezręczności, ale zapewnia sposób na złożenie skargi za każdym razem, gdy używana jest przestarzała funkcja, przy jednoczesnym zachowaniu możliwości y użycia HOF.

0

To naprawdę zależy od sposobu zaprojektowania DSL. Jeśli można zaprojektować DSL tak, że każda forma musi być zapakowane w go lub coś podobnego zaproszenia następnie można napisać ten go makro który robi coś takiego:

  1. macroexpand-all (od clojure.walk) do formularza przekazywane
  2. Użyj postwalk (z clojure.walk) na powyższym zwróconym formularzu i sprawdź, czy którykolwiek z napotkanych symboli nie jest uznany za przestarzały, prawdopodobnie patrząc na jakąś globalną listę przestarzałych symboli. Może być konieczne wykonanie resolve symboli, aby uzyskać nazwę kwalifikowaną nazwy obszaru.
  3. Jeśli znaleziono jakiś nieaktualny symbol, pojawi się komunikat drukowania.
  4. Powrócić formularz wejściowy, jak jest.

To makro go może być użyte do innego wstępnego przetworzenia twojego DSL, ponieważ jest to punkt wejścia twojego DSL.

UWAGA: Może zajść potrzeba znalezienia rozwiązania, w którym użytkownik użyje tej samej nazwy dla swojego własnego symbolu z jednego z nieaktualnych symboli, ale znowu może nie być to konieczne w zależności od projektu DSL.