Почему использование foreach
, map
, flatMap
и т.д. считается лучше, чем использование get
для Scala Options? Если я использую isEmpty
, я могу безопасно позвонить get
.
Почему foreach лучше, чем получить для Scala Options?
Ответ 1
Ну, это вроде как возвращается, чтобы "рассказать, не спрашивать". Рассмотрим эти две строки:
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
все начинает быстро запутываться.
Ответ 2
Одна из приятных причин использовать foreach
- это разбор чего-либо с вложенными параметрами. Если у вас есть что-то вроде
val nestedOption = Some(Some(Some(1)))
for(opt1 <- nestedOption;
opt2 <- opt1;
opt3 <- opt2) println(opt3)
Консоль печатает 1
. Если вы распространите это на случай, когда у вас есть класс, который опционально содержит ссылку на что-то, что, в свою очередь, хранит другую ссылку, то для понимания вы можете избежать гигантской "пирамиды" проверки None/Some.
Ответ 3
Есть уже отличные ответы на фактический вопрос, но для более Option
-foo вам обязательно нужно проверить Титановый лист возможностей Тони Морриса.
Ответ 4
Причина, по которой более удобно применять такие вещи, как 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
.
Ответ 5
Проще говоря:
-
Если вам нужно что-то сделать (процедура, когда вам не нужно фиксировать возвращаемое значение каждого вызова), только если опция определена (т.е. есть
Some
): используйтеforeach
( если вы заботитесь о результатах каждого вызова, используйтеmap
) -
Если вам нужно что-то сделать, если определенная опция и что-то еще, если это не так: используйте
isDefined
в выражении if -
Если вам нужно значение, если параметр является
Some
, или значением по умолчанию, если оноNone
: используйтеgetOrElse
Ответ 6
Попытка выполнить наши операции с get
более насущным стилем, где вам нужно делать то, что нужно делать и как делать. Другими словами, мы диктуем вещи и копаем больше в внутренности Options
. Где map,flatmap
- более функциональный способ делать вещи, где мы говорим, что делать, а не как делать.