Por que não podemos escrever funções abreviadas aninhadas no Clojure?

11

Hoje, tentei avaliar uma expressão Clojure com funções abreviadas aninhadas, e isso não me deixou.

A expressão foi:

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

A saída foi:

IllegalStateException Nested #()s are not allowed  clojure.lang.LispReader$FnReader.invoke (LispReader.java:630)
...and a bunch of other garbage
Lincoln Bergeson
fonte
2
Eu acho que não poder escrever esse código é uma coisa boa para o clojure.
Simon Bergot
3
Porque faz seus olhos sangrarem.
Michael Shaw
Você não precisa de (# (+% 1 (# (+% 2 (*% 3% 4))% 5)) 5)?
innova

Respostas:

5

Você saberia que% pertence à função interna. A desvantagem é que você perderia acesso ao% na função externa.

Use a fn [x]sintaxe.

Robert Harvey
fonte
1
Então? Na maioria das vezes eu não preciso ter acesso ao %arquivo externo e, nas vezes em que você fez isso, você poderia voltar (fn), certo?
Zaz
10

É completamente arbitrário; há algumas linhas no analisador que o desabilitam explicitamente. Se você editar essa linha, poderá ter funções anônimas aninhadas e elas agem exatamente como você esperaria.

especificamente, linhas 634-635 em 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
fonte
Você pode identificar a linha no analisador e demonstrar que o código reescrito para não ter uma função aninhada e o código com a linha removida do analisador e uma função aninhada funcionam da mesma maneira?
2
@ MichaelT: lá vai você. e você pode apenas testá-lo; é fácil, pois você pode trocá-los em tempo de execução. o analisador clojure é realmente muito facilmente hackable
amara
4
Bem, não é completamente arbitrário; a menos que Rick Hickey estivesse apenas tendo um dia arbitrário, deve ter havido uma razão para ele colocar lá, e você parece não saber qual é a razão. Duh.
Robert Harvey
Uau, que descoberta! Bom - +1.
Essa mudança causaria análises ambíguas de métodos aninhados? Estou curioso para fn [x]reescrever o código do OP teria funcionalidade idêntica a uma versão modificada do clojure. Além disso, haveria algum problema com a portabilidade do código de clojure?
3

Você pode ter funções anônimas aninhadas do tipo (fn [params] (body)). Apenas a sintaxe # não suporta aninhamento.

WolfeFan
fonte