Почему foreach лучше, чем Scala Options? - PullRequest
45 голосов
/ 25 июля 2011

Почему использование foreach, map, flatMap и т. Д. Считается лучше, чем использование get для параметров Scala? Если я использую isEmpty, я могу безопасно позвонить get.

Ответы [ 6 ]

76 голосов
/ 25 июля 2011

Ну, это вроде как "говори, не спрашивай".Рассмотрим эти две строки:

if (opt.isDefined) println(opt.get)
// versus
opt foreach println

В первом случае вы смотрите внутрь opt, а затем реагируете в зависимости от того, что видите.Во втором случае вы просто говорите opt, что вы хотите сделать, и позволяете ему разобраться с этим.

Первый случай слишком много знает о Option, копирует внутреннюю логику, хрупок и склоненк ошибкам (это может привести к ошибкам во время выполнения, а не к ошибкам во время компиляции, если они записаны неправильно).

Добавьте к этому, он не может быть компонован.Если у вас есть три варианта, один для понимания позаботится о них:

for {
  op1 <- opt1
  op2 <- opt2
  op3 <- opt3
} println(op1+op2+op3)

С if все начинает быстро запутываться.

21 голосов
/ 25 июля 2011

Одна хорошая причина для использования foreach - это анализ чего-либо с вложенными параметрами. Если у вас есть что-то вроде

val nestedOption = Some(Some(Some(1)))
for {
  opt1 <- nestedOption
  opt2 <- opt1
  opt3 <- opt2
} println(opt3)

Консоль печатает 1. Если вы распространите это на случай, когда у вас есть класс, который необязательно хранит ссылку на что-то, что, в свою очередь, хранит другую ссылку, для понимания, вы можете избежать гигантской «пирамиды» проверки None / Some.

17 голосов
/ 26 июля 2011

Уже есть отличные ответы на актуальный вопрос, но для более Option -foo вы обязательно должны проверить Tony Morris 'Option Cheat Sheet .

6 голосов
/ 25 июля 2011

Причина, по которой более полезно применять такие вещи, как map, foreach и flatMap непосредственно к Option вместо использования get, а затем выполнение функции, заключается в том, что она работает на Some или None, и вам не нужно делать специальные проверки, чтобы убедиться, что значение там.

val x: Option[Int] = foo()
val y = x.map(_+1) // works fine for None
val z = x.get + 1  // doesn't work if x is None

Результат для y здесь равен Option[Int], что желательно, поскольку, если x является необязательным, то y также может быть неопределенным. Так как get не работает на None, вам придется проделать кучу дополнительной работы, чтобы убедиться, что вы не получили никаких ошибок; дополнительная работа, выполненная для вас map.

2 голосов
/ 14 октября 2016

Проще говоря:

  • Если вам нужно что-то сделать (процедура, когда вам не нужно захватывать возвращаемое значение каждого вызова), только если опция определена (т.е.Some): используйте foreach (если вас интересуют результаты каждого вызова, используйте map)

  • Если вам нужно что-то сделать, если параметр определен ичто-то еще, если это не так: используйте isDefined в операторе if

  • Если вам нужно значение, если опция Some, или значение по умолчанию, если оно None: используйте getOrElse

0 голосов
/ 14 октября 2016

Попытка выполнить наши Операции с get - это более императивный стиль, когда вам нужно сказать , что делать и как делать .Другими словами, мы диктуем вещи и копаем больше во Options внутренностях.Где, как map,flatmap более функциональный способ делать вещи, где мы говорим , что делать, но не как .

...