F # Условные выражения, если & hellip; then..else return unit или ()

Swiftz уже предлагает Future, который является основным строительным блоком Promise. Будущее - это обещание, которое не может потерпеть неудачу (все термины здесь основаны на интерпретации Scala, , где Promise является монадой ).

https: // github. com / maxpow4h / swiftz / blob / master / swiftz / Future.swift

Надеюсь, что в какой-то момент мы сможем написать его в полной версии в стиле Скала (я могу написать это сам в какой-то момент; Конечно, другие PR будут приветствоваться, это не так сложно, если будущее уже на месте).

В вашем конкретном случае я, вероятно, создаю Result<[Book]> (на основе версии Александроса Салазара Result [/ д2]). Тогда ваша сигнатура метода будет:

class func fetchGenres() -> Future> {

Примечания

  • Я не рекомендую функции префикса с get в Swift. Это нарушит определенные виды совместимости с ObjC.
  • Я рекомендую развернуть весь путь до объекта Book, прежде чем возвращать результаты в качестве Future. Существует несколько способов, с помощью которых эта система может выйти из строя, и гораздо удобнее, если вы проверите все эти вещи, прежде чем обернуть их в Future. Переход к [Book] намного лучше для остальной части вашего кода Swift, чем передача NSArray.

6
задан Brett Rowberry 13 July 2018 в 13:36
поделиться

4 ответа

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

let f a = if a > 5 then true

Если вы вызываете f 10, он возвращает true.

Теперь спросите себя: что должно f 2 вернуться? Я знаю, что вы скажете false, но как компилятор это знает? Я имею в виду, что это так же вероятно, что вы хотели, чтобы он вернулся true в обоих случаях, не так ли? Или даже, возможно, сбой в случае a <= 5, кто знает?

Итак, чтобы программа была «полной» (т.е. содержала инструкции о том, что делать в любой ситуации), вы всегда имеете для указания ветви else.


unit, однако, special .

Возврат unit означает, что нет значащее возвращаемое значение. По существу unit означает побочный эффект: это означает, что вещь, которая вернула его, должна была произвести некоторый эффект во внешнем мире. Так как F # не является чистым языком, то такие unit -повторящие вещи довольно повсеместны. Например, ведение журнала отладки:

let f x =
    if x < 42 then printfn "Something fishy, x = %d" x
    x + 5

С такими утверждениями нет никакой двусмысленности: всегда известно, что ветвь else предназначена для возврата (). В конце концов, нет других значений unit, есть ли? В то же время, всегда добавляя else () в конце, было бы очень утомительно и запутывать. Таким образом, в интересах удобства использования компилятор не нуждается в ветви else в этом конкретном случае.

9
ответ дан Fyodor Soikin 17 August 2018 в 12:42
поделиться
  • 1
    Когда блок задействован, «всегда добавление else () в конце будет очень утомительным и запутывающим». Я согласен, я только ожидал, что это будет принятое решение - я рад, что это не так! – Brett Rowberry 13 July 2018 в 15:02

В F # if есть выражение, а не оператор. Каждое выражение должно возвращать значение. И оба if и else должны возвращать одинаковый тип значения, потому что F # - строго типизированный язык. Поэтому, если нет ветки else, то по умолчанию у нее есть тип unit, но если ваш if возвращает значение с типом, отличным от unit, тогда вам нужно иметь else с тем же типом ,

2
ответ дан Aaron M. Eshbach 17 August 2018 в 12:42
поделиться

Типы значений, создаваемых в каждой ветви, должны совпадать. Если нет явной ветви else, ее тип является единицей. Поэтому, если тип ветви then - это любой тип, отличный от единицы, должна быть ветвь else с тем же типом возвращаемого значения.

Если вы удалите else из первый фрагмент, это эквивалентно

let x = 
    if ("hello" = null) 
    then true
    else ()

, который не проверяет тип.

Почему? Я предполагаю, что для совместимости с OCaml.

Часть else expr3 может быть опущена, и в этом случае она по умолчанию else (). (7.7.2)

Вы можете думать о unit - возвращении if в качестве эквивалента оператора C-like if в отличие от выражения.

1
ответ дан Alexey Romanov 17 August 2018 в 12:42
поделиться
  • 1
    Это не имеет ничего общего с совместимостью с OCaml. – Fyodor Soikin 13 July 2018 в 14:22
  • 2
    В том смысле, что если OCaml не позволяет исключить else (например, SML), могут ли его конструкторы F #? & Quot; Я ожидаю, что ответ будет «нет, они не будут». – Alexey Romanov 13 July 2018 в 14:35
  • 3
    Хотя это может быть правдой, это не является основанием для обоснования такого поведения. Если вы игнорируете связь с OCaml, по-прежнему существует причина использования if без else, как объясняет ответ Фёдора. – Aaron M. Eshbach 13 July 2018 в 14:44
  • 4
    Кроме того, в F # есть много вещей, которые были добавлены для уменьшения повторяемости и не существуют в OCaml, например. легкий синтаксис. – Fyodor Soikin 13 July 2018 в 15:07
  • 5
    Речь идет о том, почему F # в частности делает это против того, почему языки с if-выражениями стремятся сделать это (даже если не всегда). Мое лучшее доказательство традиции по принципу состоит в том, что по той же причине, объясненной Федором, следует применять к совпадениям с возвратом модели: почему не всегда приходится добавлять | _ -> () «очень утомительные и запутывающие»? – Alexey Romanov 13 July 2018 в 18:35

Вопрос уже ответил, поэтому я просто буду следить за своими собственными поверхностными наблюдениями

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

В C #, где if - это утверждение, это имеет смысл

if(x)
{
  return 1;
}

Если x истинно, выполнение останавливается, и мы возвращаем вызывающему пользователю результат: 1.

В F #, где if выражение означает, что if должно давать значение независимо от того, какая ветвь была взята. Поэтому это мало смысла

if x then 1 // What value should else branch evaluate to?

Мы должны указать обе ветви

if x then 1 else 0

. Как и другие ответы, существует специальный случай, когда else опущен. Выражение if будет выдавать значение unit, самое близкое, что мы получаем к утверждению в F #. Поскольку тип выражения if является единицей, ветвь «истина» должна иметь тип unit.

if x then ()         // This works
if x then () else () // This works
if x then 1          // This won't work, type mismatch
1
ответ дан Just another metaprogrammer 17 August 2018 в 12:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: