7
votes

Comment faire une simulation numérique avec des données immuables dans le clojure?

J'utilise Clojure et je dois courir une petite simulation. J'ai un vecteur de longueur n (n est généralement compris entre 10 et 100) qui détient des valeurs. Sur chaque tour de simulation (peut-être 1000 tours ensemble), l'une des valeurs du vecteur est mise à jour au hasard. Je suppose que je pouvais le faire en utilisant un tableau Java et en appelant la méthode ASET, mais cela enfreindrait la programmation fonctionnelle / Immutabilité Idiom.

Y a-t-il un moyen plus fonctionnel de le faire, ou devrais-je simplement aller avec le tableau Java?


0 commentaires

4 Réponses :


1
votes

Ce n'est pas que Clojure ne vous laisse pas changer de valeur, c'est un peu plus encombrant. XXX

Pour examiner les valeurs dans le vecteur changé, utilisez @ VEC-REF.

pourrait être désactivé dans les détails - je ne suis pas près d'une replaction, malheureusement. Mais cela devrait vous aider à démarrer.


1 commentaires

Merci, je vérifierai également cette façon de résoudre le problème.



6
votes
(defn run-sim [arr num-iters update-fn]
 (if (zero? num-iters)
   arr
   (let [i (rand-int (count arr))
         x (update-fn)]
     (println "setting arr[" i "] to" x)
     (recur (assoc arr i x) (dec num-iters) update-fn))))

user> (run-sim [1 2 3 4 5 6 7 8 9 10] 10 #(rand-int 1000))
setting arr[ 8 ] to 167
setting arr[ 4 ] to 977
setting arr[ 5 ] to 810
setting arr[ 5 ] to 165
setting arr[ 3 ] to 486
setting arr[ 1 ] to 382
setting arr[ 4 ] to 792
setting arr[ 8 ] to 478
setting arr[ 4 ] to 144
setting arr[ 7 ] to 416
[1 382 3 486 144 165 7 416 478 10]
There's no shame in using a Java array if you need it though.  Especially if you need it to go fast.  Limit the array-mutation to the inside of your function (clone the input array and work on that maybe) and no one will be the wiser.

0 commentaires

2
votes

permet d'abord définir une fonction qui met à jour un index aléatoire dans un vecteur avec une nouvelle valeur. Notez que le vecteur d'origine n'est pas modifié, un nouveau vecteur (avec la valeur mise à jour) est renvoyé: xxx

Cette fonction choisit un index puis d'augmenter ou diminue la valeur à cet indice. Par 1. Vous devez bien sûr changer cette fonction à vos besoins.

Ensuite, il s'agit d'une matière simple pour composer cette fonction avec elle-même autant de fois que vous souhaitez exécuter la simulation: xxx


1 commentaires

Merci pour la réponse, cette approche de composation semble également intéressante.



5
votes

Ajout à la réponse de Brian: Si vous avez besoin de plus de vitesse, vous pouvez également recourir à des transitoires. XXX


2 commentaires

Merci! Je vais devoir creuser dans cette affaire transitoire, la vitesse est toujours bonne!


Les transitoires sont faciles: appelez (chose transitoire) au début. Ajouter un ! aux opérations, par exemple. Assoc!, dissocier! etc. Appelez (persistant! TRANSIENT-chose) lorsque vous retournez. Vous ne devez pas fuir les transitoires en dehors de votre fonction, cependant.