Mengapa kita tidak bisa menulis fungsi tulisan cepat bersarang di Clojure?

11

Saya mencoba untuk mengevaluasi ekspresi Clojure dengan fungsi tulisan cepat bersarang hari ini, dan itu tidak membiarkan saya.

Ungkapannya adalah:

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

Outputnya adalah:

IllegalStateException Nested #()s are not allowed  clojure.lang.LispReader$FnReader.invoke (LispReader.java:630)
...and a bunch of other garbage
Lincoln Bergeson
sumber
2
saya menemukan bahwa tidak dapat menulis kode seperti itu adalah hal yang baik untuk clojure.
Simon Bergot
3
Karena itu membuat mata Anda berdarah.
Michael Shaw
Tidakkah Anda membutuhkan (# (+% 1 (# (+% 2 (*% 3% 4))% 5)) 5)?
innova

Jawaban:

5

Anda akan tahu bahwa% milik fungsi dalam. Kekurangannya adalah Anda akan kehilangan akses ke% di fungsi luar.

Gunakan fn [x]sintaks sebagai gantinya.

Robert Harvey
sumber
1
Begitu? Sebagian besar waktu saya tidak perlu akses ke %fn luar, dan pada saat Anda melakukannya, Anda bisa mundur (fn), kan?
Zaz
10

Ini sepenuhnya arbitrer; ada beberapa baris di parser yang secara eksplisit menonaktifkannya. Jika Anda mengedit garis itu, Anda dapat memiliki fungsi anonim bersarang, dan mereka bertindak persis seperti yang Anda harapkan.

secara khusus, baris 634-635 di 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
sumber
Bisakah Anda mengidentifikasi baris di parser dan menunjukkan bahwa kode ditulis ulang untuk tidak memiliki fungsi bersarang dan kode dengan garis dihapus dari parser dan fungsi bersarang anon bekerja sama?
2
@MichaelT: ini dia. dan Anda bisa mengujinya; itu mudah dilakukan karena Anda dapat mematikannya saat runtime. ploer clojure sangat mudah diretas
amara
4
Yah, tidak sepenuhnya sewenang-wenang; kecuali Rick Hickey hanya mengalami hari yang sewenang-wenang, pasti ada alasan dia memasukkannya ke sana, dan sepertinya kau tidak tahu apa alasannya. Duh.
Robert Harvey
Wow, penemuan yang luar biasa! Bagus - +1.
Apakah perubahan ini menyebabkan parsing metode bersarang ambigu? Saya ingin tahu fn [x]penulisan ulang kode OP akan memiliki fungsi yang identik dengan versi clojure yang dimodifikasi. Selain itu, apakah akan ada masalah dengan portabilitas kode clojure?
3

Anda dapat memiliki fungsi anonim bersarang dari jenis (fn [params] (body)). Hanya sintaks # yang tidak mendukung penyatuan.

WolfeFan
sumber