2015-01-29 1 views
2

Я хотел бы иметь возможность определить анонимную функцию в моем проекте Lieningen с помощью Environ.Определение функции в Environ (Clojure), а затем ее использование в коде

Вот что та часть файла проекта выглядит следующим образом:

{:env {:foo (fn [s] 
       (count s))}} 

Тогда в моем коде, я хотел бы использовать эту функцию. Что-то вроде:

(-> "here are a few words" 
    (env :foo)) 

И вот, чтобы получить размер s.

ответ

4

Environ просто вызывается read-string на удаленный файл. Значение в :foo будет списком, содержащим символ fn, за которым следует вектор с символом s внутри и так далее. то есть форма не была оценена и поэтому вы не сможете вызвать анонимный fn.

см environ.core/read-env-file

Рассмотрим это:

(def f (read-string "(fn [s] (count s))")) 

(f "test") 
;; => ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.IFn 

(def evaled-f (eval (read-string "(fn [s] (count s))"))) 
(evaled-f "test") 
;; => 4 

Кроме того, ваше назначение является поодаль. -> - это макрос, который возьмет первый аргумент arg и «введет» его в первую позицию следующей формы.

(macroexpand '(-> "here are a few words" (env :foo))) 
;; => (env "here are a few words" :foo) 

Я думаю, что вы ищете что-то вроде:

(let [f (eval (env :foo))] 
    (-> "here are a few words" 
     f)) 
+0

спасибо за это замечательное объяснение, именно то, что я искал! – Neoasimov

0

(env :foo) списка.Возвраты. Для того, чтобы функция из него вы можете использовать eval или лучше макрос так:

(defmacro defn-env [fn-name env-key] 
    `(def ~fn-name ~(env env-key))) 

(defn-env env-fn :foo) ; => #'user/env-fn 

(env-fn [1 2 3]) ; => 3 

Примечание: если (env :foo) возвращает nil вам необходимо добавить к вашему :plugins [[lein-environ "1.0.0"]]project.clj.

Смежные вопросы