Аспектно-ориентированное программирование на Clojure

Это работает. Но почти наверняка не так, как вы думаете, это работает.

PS> $a = 42;
PS> [scriptblock]$b = { $a }
PS> & $b
42
17
задан Chiron 6 April 2011 в 21:52
поделиться

1 ответ

Хорошо Вы могли быть большим количеством AOP w/Clojure легко. Просто используйте метаданные в функциях к informe, когда Вы захотите журналы:

(defn ^:log my-calculation 
  [a b]
  (+ a b))

Затем можно переопределить все функции, перенеся их w/, регистрирующийся автоматически. Часть этого кода (вместе w/разворачивают рев функций):

(defn logfn
  [f topic severity error-severity]
  (fn [& args]
    (try
      (if severity
        (let [r (apply f args)]
          (log* topic {:args args, :ret r} severity)
          r)
        (apply f args))
      (catch Exception e
        (if error-severity
          (let [data {:args args, :error (treat-error e), :severity error-severity}]
            (log* topic data error-severity)
            (throw e))
          (throw e))))))

(defn logfn-ns
  "Wrap function calls for logging on call or on error.

  By default, do nothing. When any :log or :log-error, enables logging. If ^:log,
  only log on error (default severity error).

  Can customize log severity w/ e.g. ^{:log info} or on error log severity likewise."
  [ns alias]
  (doseq [s (keys (ns-interns ns))
          :let [v (ns-resolve ns s)
                f @v
                log (-> v meta :log)
                log-error (-> v meta :log-error)]
          :when (and (ifn? f)
                     (-> v meta :macro not)
                     (-> v meta :logged not)  ;; make it idempotent
                     (or log log-error))]

    (let [log (if (= log true) nil log)
          log-error (or log-error "error")
          f-with-log (logfn f
                            (str alias "/" s)
                            log
                            log-error)]
      (alter-meta! (intern ns s f-with-log)
                   (fn [x]
                     (-> x
                         (assoc :logged true)
                         (assoc :unlogged @v)))))))

(defn unlogfn-ns
  "Reverts logfn-ns."
  [ns]
  (doseq [s (keys (ns-interns ns))
          :let [v (ns-resolve ns s)]
          :when (-> v meta :logged)]
    (let [f-without-log (-> v meta :unlogged)]
      (alter-meta! (intern ns s f-without-log)
                   (fn [x]
                     (-> x
                         (dissoc :logged)
                         (dissoc :unlogged)))))))

Вы просто звоните (log/logfn-ns 'my.namespace "some alias"), и все перенесено w/, регистрирующийся (и некоторые).

пз: Мой пользовательский регистратор выше имеет topic, который является "некоторым псевдонимом/именем функции" PS2: Также перенесенная попытка/выгода w/. PS3: не любил это так. Вернувшийся, чтобы иметь явный вход.

0
ответ дан 30 November 2019 в 10:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: