Создание взаимно рекурсивных локальных функций с метаданными в Clojure - PullRequest
0 голосов
/ 08 февраля 2019

Предположим, я хочу определить две взаимно рекурсивные функции в локальной области видимости.Я могу сделать это с помощью letfn:

(letfn 
  [(f [x] (if (= x 0) (g x) true))
   (g [x] (if (= x 1) (f x) false))]
 (f 0))

Но letfn довольно ограничен по сравнению с let, так как он принимает только "спецификации функций", а не произвольные выражения.Мой вопрос: что, если я хочу присоединить метаданные (используя with-meta) к f и g, чтобы в f я мог читать метаданные g, а в g,Я могу прочитать метаданные f?Возможно ли это в Clojure?

(Для контекста я пытаюсь реализовать макрос, подобный fn, который автоматически присоединяет определенные метаданные к создаваемой функции. Я хотел бы, чтобы эти авто-аннотированные fnбыть инстанцируемым везде, где есть обычная функция Clojure, в том числе внутри letfn. Но я не понимаю, как я могу определить letfn -подобный макрос, который присоединяет метаданные, потому что в конечном итоге он должен был бы десагар до letfn, который не может прикрепить метаданные.)

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

Не забудьте о with-local-vars:

  (with-local-vars [f (fn [x] (if (= x 0) (g x) true))
                    g (fn [x] (if (= x 1) (f x) false))]
    (reset-meta! f {:f 3})
    (reset-meta! g {:g 2})

с результатами:

(f 0) => false
(f 1) => true

f           => #<Var: --unnamed-->
(var-get f) => #object[tst.demo.core$fn__20698$fn__20699 0x1eb2d718 "tst.demo.core$fn__20698$fn__20699@1eb2d718"]
(meta f)    => {:f 3}
(meta g)    => {:g 2}

Вы также можете использовать var-get и var-set для доступа / изменения значенияиз местных вар.

0 голосов
/ 08 февраля 2019

Я нашел следующее решение, в котором letfn используется для определения блоков, которые соответствуют действительным функциям f и g:

(letfn [(f-thunk [] 
          (with-meta (fn f [] (let [g (g-thunk)] (meta g))) {:f 3})) 
        (g-thunk [] 
          (with-meta (fn g [] (let [f (f-thunk)] (meta f))) {:g 2}))]
  (let [f (f-thunk) g (g-thunk)]
    [(f) (g)]))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...