6 votes

Que signifie swap ! avec assoc et la syntaxe (-> % .-target .-value) en ClojureScript ?

J'essaie de comprendre ce morceau de code tiré du livre Web Development With Clojure. Il s'agit de clojure script :

(defn message-form [] 
  (let [fields (atom {})] 
   (fn [] 
    [:div.content
     [:div.form-group 
      [:p "Name:"
       [:input.form-control 
        {:type :text 
         :name :name 
         :on-change #(swap! fields assoc :name (-> % .-target .-value)) 
         :value (:name @fields)}]]] 
    [:p "Message:"
     [:textarea.form-control 
      {:rows 4 
       :cols 50 
       :name :message 
       :on-change #(swap! fields assoc :message (-> % .-target .-value))} 
      (:message @fields)]] 
    [:input.btn.btn-primary {:type :submit :value "comment"}]]))) 

Quelqu'un peut-il expliquer cette partie :

#(swap! fields assoc :name (-> % .-target .-value)

surtout ceci : ...(-> % .-target .-value)

5voto

Svante Points 24355
[:input {:on-change #(swap! fields assoc :name (-> % .-target .-value)}]

Ceci définit une entrée et une fonction qui sera appelée chaque fois que l'utilisateur modifie le champ d'entrée, c'est-à-dire qu'il le tape. La fonction sera appelée avec l'objet d'événement de changement comme argument, qui est ensuite lié à % . La cible de l'événement est l'élément DOM du champ de saisie, qui a pour nom value son contenu textuel. La fonction modifie ensuite fields à contenir comme :name ce contenu.

Le site #(…) et le % appartiennent ensemble : #(…) crée une fonction anonyme et % est le nom de son paramètre.

Le site -> est une macro qui inverse la composition habituelle des formes en préfixe lispy en quelque chose qui ressemble à une composition en postfixe ou "piping" : (-> % .-target .-value) est étendu à (.-value (.-target %)) .

Le site .-value est l'interopérabilité de JavaScript dans ClojureScript. Elle désigne l'accès à un champ "valeur" d'un objet JavaScript ; (.-value foo) en ClojureScript est essentiellement la même chose que d'écrire foo.value o foo["value"] en JavaScript.

3voto

Chris Murphy Points 41

Dans votre question swap! c'est prendre un atome, une fonction ( assoc ) qui met à jour la valeur que l'atome stocke y les arguments ultérieurs qui sont donnés à la fonction.

Voici une autre façon d'obtenir le même résultat :

#(swap! fields (fn [prev] (assoc prev :name (-> % .-target .-value)))

Voir que :name y (-> % .-target .-value) seraient les deux arguments suivants dans le swap! l'invocation de votre question, où apply est utilisé en interne pour appliquer ces arguments à assoc . Ici, il n'y a qu'une fonction de mise à jour - aucun argument ultérieur.

Comme vous pouvez le constater prev est la valeur interne de l'atome que nous allons modifier et swap! prend simplement une fonction de mise à jour, qui renvoie la valeur suivante pour la fonction swap! à stocker.

En ce qui concerne (-> % .-target .-value) va, rappelez-vous que vous êtes déjà dans la macro du lecteur, donc % est son premier argument. Le site -> La macro de filetage est intégrée au premier argument de chaque fonction suivante, de sorte que % est donné à .-target et le résultat de cette opération est donné à .-value en nous donnant : (.-value (.-target %)) .

:name dans la carte stockée dans les champs est définie comme la valeur cible d'une valeur fournie !

Sortir un peu plus large % est un événement JavaScript qui est fourni chaque fois que le champ de saisie de texte est modifié - en fait, chaque fois que l'utilisateur tape du texte. Il est rare que vous souhaitiez obtenir l'intégralité de l'événement, mais seulement le texte qui a été saisi. C'est là qu'intervient la récupération de la cible de l'événement (par opposition à la source), puis de la valeur de cette cible. Le site .- signifie que vous obtenez une propriété JavaScript - c'est de l'interopérabilité, par opposition à la syntaxe ClojureScript normale.

2voto

akond Points 6145

#() es un macro lecteur . Il s'agit d'une forme abrégée pour une fonction anonyme (fn [args] ...) , donde % est le premier argument de cette fonction.

Dans ce cas particulier #(swap! fields assoc :name (-> % .-target .-value) est égal à (fn [X] (swap! fields assoc :name (-> X .-target .-value))

-> es un macro de filetage y (-> X .-target .-value) est équivalent à (.-value (.-target X)) .

(.-target X) signifie obtenir des biens target de l'objet X .

Vous définissez donc une fonction anonyme qui reçoit un seul argument. Cette fonction va changer le fields de sorte que sa clé :name sera défini comme la valeur de la propriété value de l'objet dans la propriété target de l'objet X .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X