Czy ktoś wie, jak wdrożyć metodę method_missing (à la Ruby) w Clojure? E.g.Metoda Clojure brakująca
(defn method_missing [name & args]
(foo name args))
Byłoby bardzo przydatne dla DSL, jeśli jest używany prawidłowo.
Z góry dziękuję!
Czy ktoś wie, jak wdrożyć metodę method_missing (à la Ruby) w Clojure? E.g.Metoda Clojure brakująca
(defn method_missing [name & args]
(foo name args))
Byłoby bardzo przydatne dla DSL, jeśli jest używany prawidłowo.
Z góry dziękuję!
W języku Ruby, method_missing
jest jedną z głównych konstrukcji do metaprogramowania. Jest ściśle związana z obiektową strukturą Ruby, dynamicznie tworząc metody w klasie z "metaclasses". Można to zrobić, ponieważ w klasach Ruby są również obiekty.
Ponieważ Clojure jest językiem funkcjonalnym, naśladowanie tego rubinizmu ma niewielki sens. Jednak jednym z podstawowych idiomów Lisps (takich jak Clojure) jest to, że kod to dane: a ponieważ kod może generować dane, może również generować kod. Podstawowym sposobem wykonywania tego metaprogramowania w Lisp są makra.
Sugeruję więcej informacji na temat makr oraz ich zaleceń i zakazów. Należy jednak pamiętać, że tak jak w Ruby, generowanie dynamicznie kodu jest ogólnie trudniejsze do debugowania i utrzymywania. Często sprytne użycie innych funkcjonalnych idiomów może być lepszym rozwiązaniem konstrukcyjnym.
Zgadzam się z większością tego, ale nie zgadzam się z twierdzeniem, że kod generowany dynamicznie jest trudny do debugowania lub utrzymywania. Makra są wielką korzyścią dla uproszczenia i łatwości konserwacji, pod warunkiem, że są wykorzystywane ze smakiem. – amalloy
Chcąc wskazać, kiedy należy używać makr, należy dokładnie rozważyć, a kiedy można zrobić coś z normalnymi funkcjami, powinno to być preferowane. – NielsK
Jako że sam pochodziłem z Ruby, zrozumienie mocy kompozycji funkcyjnej może zająć trochę czasu. Używanie makr do obejścia tego może przynieść efekt odwrotny do zamierzonego. – NielsK
Można utworzyć makro, które będzie zawijać wywołania funkcji w bloku try-catch, który przechwyciłby ten wyjątek.
np. Coś jak
(with-default-method [fxn args default] ...)
rozwinie się do
(try (fxn args) (catch java.lang.IllegalArgumentException _) (finally default))
powyższe jest głównie ręcznie macha, bo nie sądzę, że jest to dobry pomysł w ogóle: to nadużycie systemu wyjątków, a Myślę, że zrobi nieoczekiwane rzeczy.
Nie jestem osobą z Rubinem, ale mam wrażenie, że ta funkcja jest wypalana w tym języku; w Javie, a przez rozszerzenie clojure, musielibyście spróbować to włączyć, a to nie byłoby ładne.
W jakich przypadkach chciałbyś wywołać tę funkcję? – Brian