web - program - sum clojure




Wann sollte ein Var anstelle einer Funktion verwendet werden? (2)

Ich gehe das Clojure-Webentwicklungsbuch durch und es fordert mich auf, das Handler-Var-Objekt (definierter Balg) anstelle der Funktion selbst zu übergeben, da sich die Funktion dynamisch ändert (dies ist das, was Wrap-Reload tut).

Das Buch sagt:

"Beachten Sie, dass wir eine Variable aus dem Handler erstellen müssen, damit diese Middleware funktioniert. Dies ist erforderlich, um sicherzustellen, dass das Var-Objekt mit der aktuellen Handlerfunktion zurückgegeben wird. Wenn wir stattdessen den Handler verwenden, würde die App nur die Variable sehen Der ursprüngliche Wert der Funktion und die Änderungen würden nicht wiedergegeben. " Ich verstehe nicht wirklich, was das bedeutet. Sind VARs C-Zeigern ähnlich?

(ns ring-app.core
  (:require [ring.adapter.jetty :as jetty]
            [ring.util.response :as response]
            [ring.middleware.reload :refer [wrap-reload]]))

(defn handler [request]
  (response/response
   (str "<html>/<body> your IP is: " (:remote-addr request)
        "</body></html>")))

(defn wrap-nocache [handler]
  (fn [request]
    (-> request
        handler
        (assoc-in [:headers "Pragma"] "no-cache"))))

Hier ist der Handler-Aufruf:

(defn -main []
  (jetty/run-jetty
   (wrap-reload (wrap-nocache  (var handler)))
   {:port 3001
    :join? false}))

Es gibt bereits einige gute Antworten. Ich wollte nur diesen Vorbehalt hinzufügen:

(defn f [] 10)
(defn g [] (f))
(g) ;;=> 10
(defn f [] 11)

;; -Dclojure.compiler.direct-linking=true
(g) ;;=> 10

;; -Dclojure.compiler.direct-linking=false
(g) ;;=> 11

Wenn also die direkte Verknüpfung aktiviert ist, wird die Indirektion über eine Variable durch einen direkten statischen Aufruf ersetzt. Ähnlich der Situation mit dem Handler, aber dann mit jedem var-Aufruf, sofern Sie nicht ausdrücklich auf eine var verweisen, wie:

(defn g [] (#'f))

Hoffentlich bringt Sie dieses kleine Beispiel auf den richtigen Weg:

> (defn your-handler [x] x)
#'your-handler

> (defn wrap-inc [f]
    (fn [x]
      (inc (f x))))
> #'wrap-inc

> (def your-app-with-var (wrap-inc #'your-handler))
#'your-app-with-var

> (def your-app-without-var (wrap-inc your-handler))
#'your-app-without-var

> (your-app-with-var 1)
2

> (your-app-without-var 1)
2

> (defn your-handler [x] 10)
#'your-handler

> (your-app-with-var 1)
11

> (your-app-without-var 1)
2

Die Intuition dafür ist, wenn Sie beim Erstellen Ihres Handlers eine Variable verwenden, übergeben Sie tatsächlich einen "Container" mit einem bestimmten Wert, dessen Inhalt in Zukunft geändert werden kann, indem Sie eine Variable mit demselben Namen definieren. Wenn Sie var nicht verwenden (wie in your-app-without-var ), übergeben Sie einen aktuellen Wert dieses "Containers", der in keiner Weise neu definiert werden kann.







var