Как сделать функции доступными для eval ClojureScript? - PullRequest
0 голосов
/ 13 июня 2018

В этом блоге Дмитрия Сотникова предусмотрена функция eval-str для запуска строки, содержащей ClojureScript:

(defn eval-str [s]
  (eval (empty-state)
        (read-string s)
        {:eval       js-eval
         :source-map true
         :context    :expr}
        (fn [result] result)))

Если у меня есть какая-то функция x, которую я хочучтобы я мог звонить из строки eval, как я могу это сделать?

1 Ответ

0 голосов
/ 13 июня 2018

Ответ состоит из двух частей, при условии, что x - это переменная, связанная с функцией ClojureScript:

  1. Метаданные анализа компилятора для x должны присутствовать в состоянии, переданном какпервый аргумент cljs.js/eval.Это связано с тем, что во время компиляции известны, например, такие вещи, как арность x.
  2. Реализация JavaScript функции, связанной с x, должна присутствовать во время выполнения JavaScript.(Это особенно верно, если функция на самом деле вызывается во время вызова cljs.js/eval, а не просто ссылается.)

Если x является основной функцией (скажем,var #'cljs.core/map например), то оба эти условия автоматически выполняются.В частности, метаданные будут создаваться при вызове cljs.js/empty-state (при условии, что :dump-core равно true), а реализация основных функций уже будет загружена в среду выполнения JavaScript.

Но, скажем, x - это совершенно новая функция, которую вы хотите скомпилировать в автономной среде.«Хитрость» состоит в том, чтобы установить и повторно использовать состояние компилятора: например, поместить результат (cljs.js.empty-state) в переменную и передавать его каждому вызову cljs.js/eval.Если вы сделаете это, и один из вызовов cljs.js/eval включает компиляцию defn для x, то состояние компилятора будет изменено (на самом деле это атом), в результате чегометаданные компилятора для x будут переведены в состояние, и, конечно же, реализация JavaScript для x будет установлена ​​в среде JavaScript (благодаря оценке JavaScript, созданного для defn).

Если, с другой стороны, x - это функция, которая является частью вашей «окружающей» среды ClojureScript (скажем, предварительно скомпилированной с помощью компилятора JVM ClojureScript, но, тем не менее, доступной во время выполнения JavaScript), то онавам будет как-то организовать перевод метаданных компилятора для x в состояние, переданное cljs.js/eval.Если вы посмотрите на вывод компилятора на основе JVM, вы увидите <ns-name>.cache.json файлы, содержащие такие метаданные.Посмотрите на данные, которые находятся в этих файлах, и вы можете выяснить их структуру;с этим вы можете увидеть, как перевести необходимую информацию в состояние компилятора в [:cljs.analyzer/namespaces <ns-name>].Функция cljs.js/load-analysis-cache! существует в качестве помощника для этого варианта использования, и автономный пример - https://stackoverflow.com/a/51575204/4284484

...