F #: Больше точек возврата в функциях, как их обрабатывать? - PullRequest
6 голосов
/ 21 февраля 2011

У меня проблема при возврате значений в сложных функциях.Примеры всегда лучше:

Рассмотрим следующую функцию:

let myf (mypar: int) =
   mypar + 1

Ну, нет пробел здесь, эта функция скомпилирована правильно и подпись:

val myf: int -> int

OK, Что ж.Теперь рассмотрим этот код:

let myf (mypar: int) =
   if mypar = 2 then
      4 (* ERROR *)
   mypar + 1

Это не работает:

Ожидается, что это выражение будет иметь тип блока, но здесь имеет int

Эта ошибка возникает каждый раз, когда я пытаюсьчтобы вернуться из моей функции, когда я нахожусь внутри if, while a for или любого другого блока.Я думал, что проблема в том, что все возможные пути возврата возвращают один и тот же тип, но здесь я не понимаю, что происходит.

Обратите внимание, что если я вставляю модуль (), все работает, например:

let myf (mypar: int) =
   if mypar = 2 then
      () (* No error *)
   mypar + 1

Но это устройство не возвращает мою функцию !!!это продолжается !!!Кроме того, не могли бы вы объяснить, как F # справляется с этим ???

Спасибо

Ответы [ 3 ]

14 голосов
/ 21 февраля 2011

Чтобы добавить больше деталей, проблема с вашим подходом состоит в том, что все в F # является выражением . Это значительно упрощает анализ ваших программ (поскольку вам не нужно отслеживать выполняемый в данный момент оператор ), но это означает, что вы всегда должны писать полное выражение.

Если вы попытаетесь написать что-то вроде return, это будет выглядеть так, как если бы вы написали следующее на C # (это, вероятно, объясняет, почему F # не допускает такого рода вещи):

int a = 10 + (3 * (return 10; 2));
return a;

Почему вы не получили ошибку, когда написали if .. then ()? Выражение () создает значение типа unit, которое является особенным, поскольку оно имеет только одно допустимое значение. F # позволяет вам писать if .. then без else при возврате unit, потому что он может выяснить, что ветвь else должна возвращать только существующее значение единицы, поэтому он видит ваш код как:

if something then ()
else () // implicitly added by the compiler

Единственная разница заключается в создании исключения (с использованием raise), которое ведет себя так же, как в C #. Вы можете выйти из функции, используя исключение, но гораздо лучше переписать код, чтобы получить полное допустимое выражение.

9 голосов
/ 21 февраля 2011

F # не имеет оператора возврата. Единственный способ сделать то, что вы хотите здесь, выбрать один или другой блок, это с помощью if .. else:

let myf (mypar: int) =
   if mypar = 2 then
      4
   else
      mypar + 1

В качестве альтернативы, исключение может досрочно выйти из функции:

let myf (mypar: int) =
   if mypar = 2 then
      failwith "invalid argument"

   mypar + 1
4 голосов
/ 21 февраля 2011

Вы пробовали использовать else вместо?

let myf (mypar: int) =
   if mypar = 2 then
      4
   else
      mypar + 1

Я сам не пробовал, но стоит попробовать :) 1005 *

(Также рассмотрите возможность использования сопоставления с образцом, конечно.)

...