Вернитесь в Scala
Я новичок scala программист и наткнулся на странное поведение.
def balanceMain(elem: List[Char]): Boolean =
{
if (elem.isEmpty)
if (count == 0)
true;
else false;
if (elem.head == '(')
balanceMain(elem.tail, open, count + 1);....
В основном я хочу вернуть true, если elem.isEmpty
и count == 0
. В противном случае я хочу вернуть false.
Теперь выше я прочитал, что нет необходимости добавлять оператор return в scala. Поэтому я опустил return
выше. Но он не возвращает логическое значение. Если я добавлю оператор return как return true
. он работает отлично. Почему это так?
Кроме того, почему считается, что плохая практика имеет операторы возврата в scala
Ответы
Ответ 1
Это не так просто, как просто опустить ключевое слово return
. В Scala, если нет return
, то последним выражением считается возвращаемое значение. Итак, если последнее выражение - это то, что вы хотите вернуть, вы можете опустить ключевое слово return
. Но если то, что вы хотите вернуть, не является последним выражением, тогда Scala не будет знать, что вы хотите вернуть его.
Пример:
def f() = {
if (something)
"A"
else
"B"
}
Здесь последнее выражение функции f
является выражением if else, которое вычисляется как String. Поскольку не указано явное return
, Scala выведет, что вы хотите вернуть результат этого выражения if/else: a String.
Теперь, если мы добавим что-то после выражения if/else:
def f() = {
if (something)
"A"
else
"B"
if (somethingElse)
1
else
2
}
Теперь последнее выражение является выражением if/else, которое вычисляется как Int. Таким образом, тип возврата f
будет Int. Если бы мы действительно хотели, чтобы он возвращал String, то у нас были проблемы, потому что Scala имеет не идею, что мы намеревались. Таким образом, мы должны исправить это, либо сохраняя String для переменной, и возвращая ее после второго выражения if/else, либо изменив порядок, чтобы последняя была последней.
Наконец, мы можем избежать ключевого слова return
даже с вложенным выражением if-else, например yours:
def f() = {
if(somethingFirst) {
if (something) // Last expression of `if` returns a String
"A"
else
"B"
}
else {
if (somethingElse)
1
else
2
"C" // Last expression of `else` returns a String
}
}
Ответ 2
Этот вопрос на самом деле немного сложнее, как описано в ответах до сих пор. Этот блог Rob Norris объясняет это более подробно и дает примеры, когда использование return действительно нарушит ваш код (или, по крайней мере, будет иметь неочевидные эффекты).
В этот момент позвольте мне просто процитировать суть поста. Самое главное утверждение в самом начале. Распечатайте это как плакат и положите его на стену: -)
Ключевое слово return
не является "необязательным" или "выводимым"; он меняет смысл вашей программы, и вы никогда не должны ее использовать.
Он дает один пример, где он действительно что-то ломает, когда вы встраиваете функцию
// Inline add and addR
def sum(ns: Int*): Int = ns.foldLeft(0)((n, m) => n + m) // inlined add
scala> sum(33, 42, 99)
res2: Int = 174 // alright
def sumR(ns: Int*): Int = ns.foldLeft(0)((n, m) => return n + m) // inlined addR
scala> sumR(33, 42, 99)
res3: Int = 33 // um.
потому что
A return
выражение, когда оценивается, отказывается от текущего вычисления и возвращается к вызывающей стороне метода, в котором появляется return
.
Это только один из примеров, приведенных в связанном сообщении, и это проще всего понять. Их больше, и я очень призываю вас, пойти туда, прочитать и понять.
Когда вы приходите с императивных языков, таких как Java, сначала это может показаться странным, но как только вы привыкнете к этому стилю, это будет иметь смысл. Позвольте мне закрыть еще одну цитату:
Если вы окажетесь в ситуации, когда, как вы думаете, хотите вернуться раньше, вам нужно подумать о том, как вы определили свои вычисления.
Ответ 3
Я не программирую Scala, но я использую другой язык с неявным возвратом (Ruby). У вас есть код после блока if (elem.isEmpty)
- последняя строка кода - это то, что было возвращено, поэтому вы не получаете то, что ожидаете.
EDIT: здесь более простой способ написать свою функцию. Просто используйте логическое значение isEmpty и count, чтобы автоматически вернуть true или false:
def balanceMain(elem: List[Char]): Boolean =
{
elem.isEmpty && count == 0
}
Ответ 4
По умолчанию возвращается последний оператор функции.
В вашем примере после точки появляется другое утверждение, в котором вы хотите получить возвращаемое значение.
Если вы хотите вернуть что-либо до вашего последнего утверждения, вам все равно придется использовать return
.
Вы можете изменить свой пример следующим образом, чтобы вернуть Boolean
из первой части
def balanceMain(elem: List[Char]): Boolean = {
if (elem.isEmpty) {
// == is a Boolean resulting function as well, so your can write it this way
count == 0
} else {
// keep the rest in this block, the last value will be returned as well
if (elem.head == "(") {
balanceMain(elem.tail, open, count + 1)
}
// some more statements
...
// just don't forget your Boolean in the end
someBoolStatement
}
}
Ответ 5
Не записывайте операторы if
без соответствующего else
. Когда вы добавите else
в свой фрагмент, вы увидите, что ваши true
и false
на самом деле являются последними выражениями функции.
def balanceMain(elem: List[Char]): Boolean =
{
if (elem.isEmpty)
if (count == 0)
true
else
false
else
if (elem.head == '(')
balanceMain(elem.tail, open, count + 1)
else....