Чому ми не можемо записати вкладені скорочені функції у Clojure?


11

Я намагався сьогодні оцінити вираз Clojure за допомогою вкладених скорочених функцій, і це мені не дозволило.

Вираз:

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

Вихід був:

IllegalStateException Nested #()s are not allowed  clojure.lang.LispReader$FnReader.invoke (LispReader.java:630)
...and a bunch of other garbage

2
я вважаю, що неможливо написати такий код - це гарна річ для клоджура.
Саймон Бергот

3
Бо це змушує твої очі кровоточити.
Майкл Шоу

Вам не потрібно (# (+% 1 (# (+% 2 (*% 3% 4))% 5)) 5)?
нововведення

Відповіді:


5

Ви б знали, що% належить до внутрішньої функції. Недолік полягає в тому, що ви втратите доступ до% у зовнішній функції.

Використовуйте fn [x]замість цього синтаксис.


1
Так? Більшу частину часу мені не потрібен доступ до %зовнішнього fn, і коли ви це робили, ви могли повернутися назад (fn), правда?
Заз

10

Це абсолютно довільно; в аналізаторі є кілька рядків, які явно відключають його. Якщо ви відредагуєте цей рядок, ви можете вкласти анонімні функції, і вони діють точно так, як ви очікували.

конкретно, рядки 634-635 в 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");
        // ...

Чи можете ви ідентифікувати рядок у аналізаторі та продемонструвати, що код, перезаписаний таким чином, не має вкладеної функції anon, а код із рядком, видаленим з аналізатора, і функція вкладеної в anon працює однаково?

2
@MichaelT: там ви йдете. і ви можете просто перевірити це; це легко зробити, оскільки ви можете вимкнути їх під час виконання. аналізатор clojure насправді досить легко руйнується
amara

4
Ну, не зовсім довільно; якщо Рік Хікі просто мав довільний день, то, мабуть, була причина, що він його вклав туди, і ти, схоже, не знаєш, що це за причина. Дух.
Роберт Харві

Нічого собі, яка знахідка! Приємно - +1.

Чи спричинила б ця зміна неоднозначне розбір вкладених методів? Мені цікаво, що fn [x]перезапис коду ОП мав би ідентичний функціонал модифікованій версії clojure. Крім того, чи не виникне питання щодо переносимості коду clojure?

3

Ви можете вкласти анонімні функції типу (fn [params] (body)). Тільки синтаксис # не підтримує вкладення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.