0

Я только начинаю путешествие по FP, изучая Scala.Неизменяемый способ справиться с состоянием в scala

Теперь необходимо поддерживать List[String] в нефильтрованном веб-приложении. Когда запрос POST отправляется на конечную точку, Список должен обновляться из файла. И этот список будет использоваться, когда запрос GET отправляется на ту же конечную точку.

Теперь я стараюсь избегать использования var для сохранения списка. Я знаю, что иногда нам приходится использовать var, но просто любопытно, что есть элегантный способ справиться с этим делом. Я пробовал использовать scalaz.State Iterator и Steam. Но застрял, так как я понятия не имею, как передать текущее неизменяемое состояние на следующий запрос. Любое предложение, пожалуйста?

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 

Тогда я не знаю, как я могу передать текущее состояние следующего визита в качестве входных данных без использования var.

ответ

0

Нет бесплатного обеда. Если вы хотите избежать изменчивости и избегать сохранения состояния где-то, вам нужно работать с возвращаемыми значениями.

State не более чем функция A => B (я упростил это немного для целей), где A является начальным состоянием и B является endresult

Так что в вашем случае, модель будет выглядеть как:

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

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

Как вы можете видеть здесь, что вам нужно, чтобы обеспечить текущее состояние каждого post и get. В сообщениях будет добавлено новое сообщение из файла (введите здесь свою бизнес-логику) и верните новое состояние. А для get вам необходимо предоставить текущее состояние, чтобы получить что-то, что вы хотите. Вы можете переписать это так:

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

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

Обратите внимание, что пост возвращает вам точно A ⇒ A (где A = List[String]).

ScalaZ State дает Монада для построения цепочки функций внутри для понимания, а также некоторые дополнительные удобства (например, map, gets, put и т.д ..). Но, по существу, базовая модель будет одинаковой.

Этот код представляет собой более точно, что делает State:

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) 
    } 

Это позволяет объединить состояния и обеспечить начальное значение и «запустить» его всякий раз, когда вы хотите, не уверен, что вам действительно нужно.