Dlaczego nie możemy pisać zagnieżdżonych funkcji skrótów w Clojure?

11

Próbowałem dzisiaj ocenić wyrażenie Clojure z zagnieżdżonymi funkcjami stenograficznymi, ale nie pozwoliło mi to.

Wyrażenie brzmiało:

(#(+ % (#(+ % (* % %)) %)) 5) ; sorry for the eye bleed

Wynik był:

IllegalStateException Nested #()s are not allowed  clojure.lang.LispReader$FnReader.invoke (LispReader.java:630)
...and a bunch of other garbage
Lincoln Bergeson
źródło
2
uważam, że niemożność napisania takiego kodu jest dobra dla clojure.
Simon Bergot,
3
Ponieważ powoduje to krwawienie oczu.
Michael Shaw
Czy nie potrzebujesz (# (+% 1 (# (+% 2 (*% 3% 4))% 5)) 5)?
innova

Odpowiedzi:

5

Wiesz, że% należy do funkcji wewnętrznej. Wadą jest to, że utracisz dostęp do% w funkcji zewnętrznej.

fn [x]Zamiast tego użyj składni.

Robert Harvey
źródło
1
Więc? Przez większość czasu nie potrzebuję dostępu do %zewnętrznego fn, a w czasach, kiedy to robiłeś, mogłeś do niego wrócić (fn), prawda?
Zaz
10

Jest to całkowicie arbitralne; w parserze znajduje się kilka linii, które jawnie go wyłączają. Jeśli edytujesz tę linię, możesz zagnieżdżać anonimowe funkcje i działają one dokładnie tak, jak można się spodziewać.

w szczególności wiersze 634-635 w https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LispReader.java

public static class FnReader extends AFn{
    public Object invoke(Object reader, Object lparen) {
        PushbackReader r = (PushbackReader) reader;
        if(ARG_ENV.deref() != null) // <-- line 634
            throw new IllegalStateException("Nested #()s are not allowed");
        // ...
amara
źródło
Czy potrafisz zidentyfikować wiersz w analizatorze składni i wykazać, że kod napisany od nowa nie ma funkcji zagnieżdżonej w analizatorze anonowym, a kod z linią usuniętą z analizatora składni i funkcją zagnieżdżoną w anon działa tak samo?
2
@MichaelT: proszę bardzo. i możesz to po prostu przetestować; jest to łatwe, ponieważ można je wymieniać w czasie wykonywania. parser clojure jest naprawdę łatwy do zhakowania
amara
4
Cóż, nie do końca arbitralne; chyba że Rick Hickey miał po prostu arbitralny dzień, musiał istnieć powód, dla którego go tam umieścił, a ty chyba nie wiesz, co to za powód. Duh.
Robert Harvey,
Wow, co za znalezisko! Niezły - +1.
Czy ta zmiana spowodowałaby niejednoznaczne analizy zagnieżdżonych metod? Jestem ciekawy, że fn [x]przepisanie kodu OP miałoby identyczną funkcjonalność jak zmodyfikowana wersja clojure. Ponadto, czy pojawiłby się problem z przenośnością kodu clojure?
3

Możesz zagnieżdżać anonimowe funkcje (fn [params] (body)). Tylko składnia # nie obsługuje zagnieżdżania.

WolfeFan
źródło