Работа с некоторыми () и Option () в Scala - PullRequest
8 голосов
/ 20 февраля 2012

Я боролся с концепцией функционального способа анализа строки JSON в Scala и врезался в стену с возвращаемым Option (что-то).Я ответил на вопрос , и пришли полезные ответы.

Проблема в том, как кто-то довольно новичок в Scala, каков правильный путь?

В настоящее время яя делаю это:

import util.parsing.json.JSON._

object JsonSoap {
  def main(args: Array[String]) {
    val x = parseFull("""{"name":"Joe","surname":"SOAP"}""")

    val y = x collect {
      case m: Map[_, _] => m collect {
        case (key: String, value: String) => key -> value
      }
    }

    val z = for (m <- y; name <- m.get("name"); surname <- m.get("surname"))
    yield {
      <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
        <soap:Body>
          <Person>
            <Name>{name}</Name>
            <Surname>{surname}</Surname>
          </Person>
        </soap:Body>
      </soap:Envelope>
    }

    println(z)
  }
}

Я все еще застрял с Some ()

Есть ли хороший пример для решения моей проблемы?Конечно, это должна быть хорошо изученная территория.Как я могу улучшить свой код?

Ответы [ 3 ]

35 голосов
/ 20 февраля 2012

Вы не «застряли» с Some - у вас есть преимущество , что у вас есть Some! В Java вы застряли бы со значением, тип которого не выражал тот факт, что он может фактически не существовать!

MyThing recklessly = apiCall.getMeAThing();
recklessly.iSureHopeImNotNull();  //OH NOES!

Сравните это с этим

apiCall.getMeAThing foreach (_.cannotPossiblyBeNull)

Тип данных Option означает, что бит «возможно, не существует» вашего запроса фактически вставлен в возвращаемый тип запроса. Пожалуйста, придерживайтесь Option - через несколько недель вы будете рвать на себе волосы, когда будете писать код Java, а его там нет!

Снятие ваших возражений

Вы можете сказать :

Оу, но мне нужно взять имеющееся у меня значение и добавить к нему 1

Я говорю:

apiCall.getMeAThing map (_ + 1)

Вы могли бы сказать

Оу, но мне нужно передать его методу, по умолчанию пустая строка, если у меня есть ноль

Я говорю:

foo( apiCall.getMeAThing getOrElse "" )

Вы можете сказать

Оу, но я использую это значение для вызова другого метода API и получения чего-то еще

Я говорю:

apiCall.getMeAThing flatMap apiCall.getMeAnotherThing

Вы обязательно скажете

Оу, но это ужасно неэффективно со всеми этими созданиями объектов

Я говорю: "попробуй, все будет хорошо"

9 голосов
/ 20 февраля 2012

Обычно, когда у вас есть результат, заключенный в опцию, вы хотите использовать либо match, либо один из монадических методов map, flatMap или foreach. Например, в вашем случае мы могли бы сделать любой из этих

val output = z match {
  case Some(xml) => xml
  case None => "Invalid JSON"
}
println(output)

//or
z.foreach{println} //won't print anything if z is None

//or
println(z.getOrElse("Invalid JSON"))

В большинстве случаев вам следует избегать чего-то вроде:

if (z == None) {
  println("Invalid")
} else {
  println(Z.get)
}
4 голосов
/ 20 февраля 2012

Вот в чем дело: вы, возможно, не получили ожидаемые данные, и в этом случае невозможно вычислить z.Таким образом, ответ на ваш вопрос действительно зависит от вашего ответа на один вопрос: что вы будете делать, если вы не можете вычислить z?

Предположим, например, что вы просто нехотите напечатать что-нибудь, если z не может быть вычислено (то есть, это None).В этом случае вы делаете это:

z foreach println
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...