0

Je viens de commencer mon voyage FP tout en apprenant Scala.Manière immuable de gérer l'état dans Scala

Maintenant, une exigence est de maintenir un List[String] dans une application Web non filtrée. Lorsqu'une demande POST est envoyée à un point de terminaison, la liste doit être mise à jour à partir d'un fichier. Et la liste sera utilisée lorsqu'une requête GET est envoyée au même point de terminaison.

Maintenant, j'essaie d'éviter d'utiliser var pour enregistrer la liste. Je sais parfois que nous devons utiliser var mais juste curieux qu'il y a une manière élégante de traiter l'affaire. J'ai essayé d'utiliser scalaz.State Iterator et Steam. Mais je me suis coincé puisque je n'ai aucune idée de comment passer l'état immuable actuel à la prochaine requête. Toute suggestion, s'il vous plaît?

def update = State(l => { 
    retrieve(filepath) match { 
    case Success(lines) => (lines.split("[,\n\r]").toVector.map (_.trim), true) 
    case Failure(_) => { 
     log.error(s"Cannot retrieve the file.") 
     (l, false) 
    } 
    } 
}) 

def isContained(message: String) = State(l => (l, l.exists(message.contains))) 

/* assume the following get or post method will be invoked when GET or POST request is sent to the endpoint */ 

def post() = update(Vector.empty) // how can I pass the updated state to the get method 

def get(msg: String): Boolean = isContained(msg)(???)._2 

Alors je ne sais pas comment puis-je passer l'état actuel à la prochaine visite en entrée sans utiliser var.

Répondre

0

Il n'y a pas de repas gratuit. Si vous voulez éviter la mutabilité et éviter de stocker l'état quelque part, vous devez travailler avec les valeurs renvoyées.

State est plus qu'une fonction A => B (je l'ai un peu simplifié dans un but), où A est l'état initial et B est le endresult

Donc, dans votre cas, le modèle serait à la recherche comme:

def post(newMessage: String, state: List[String]): List[String] = { 
    newMessage :: state 
} 

def get(msg: String, state: List[String]): Boolean = { 
    state.contains(msg) 
} 

Comme vous pouvez le voir ici, vous devez fournir l'état actuel à tous les post et get. Les messages ne feraient qu'ajouter un nouveau message à partir du fichier (mettez votre logique métier ici), et retourner un nouvel état. Et pour get, vous devez fournir l'état actuel, pour être en mesure de récupérer quelque chose que vous voulez. Vous pouvez réécrire cette façon:

def post(newMessage: String): List[String] ⇒ List[String] = state ⇒ { 
    newMessage :: state 
} 

def get(msg: String): List[String] ⇒ Boolean = 
    _.contains(msg) 

Notez que vous afficher des rendements exactement A ⇒ A (où A = List[String]).

ScalaZ State vous donne Monad pour enchaîner les fonctions à l'intérieur de la compréhension, ainsi que des commodités supplémentaires (comme map, gets, put etc ..). Mais essentiellement - le modèle sous-jacent serait le même.

Ce code représente plus précisément ce State fait:

type YourListState = List[String] ⇒ List[String] 

    def post(newMessage: String, state: YourListState): YourListState = li ⇒ { 
    newMessage :: state(li) 
    } 

    def get(msg: String, state: YourListState): List[String] ⇒ Boolean = { 
    state(_).contains(msg) 
    } 

Cela vous permet de combiner des états et de fournir une valeur initiale et « exécuter » chaque fois que vous voulez, pas sûr que vous avez vraiment besoin de cela.