Почему 'printf "% A" None "выводит ноль - PullRequest
3 голосов
/ 27 апреля 2020

Почему printf выводит Some x для Some x, но <null> для None?

> printfn "%A" (Some 123);;
Some 123
val it : unit = ()

> printfn "%A" None;;
<null>
val it : unit = ()

Ответы [ 2 ]

5 голосов
/ 27 апреля 2020

В скомпилированном коде F # использует значение null для представления None случая option<'T> для эффективности. На самом деле вы можете использовать то же самое для своих собственных дискриминационных союзов, используя флаг компиляции CompilationRepresentationFlags. UseNullAsTrueValue (см. документация MSDN ).

Вы можете видеть, что это происходит используя метод Object.ReferenceEquals:

> let n = None;;
val n : 'a option

> System.Object.ReferenceEquals(n, null);;
val it : bool = true

Почему printfn "%A" просто печатает внутреннее представление, а не признает, что это на самом деле представляет None случай?

Я думаю, что ответ эта печать выполняется динамически с использованием отражения, поэтому в какой-то момент аргумент просто преобразуется в значение типа obj. Если у вас есть значение null типа obj, невозможно восстановить тип, который был до приведения, и поэтому вы не можете обнаружить, что null фактически представляет None (потому что null.GetType() не удается). Предположительно, печать могла бы использовать информацию о типе stati c для получения информации о типе таким образом, но это, вероятно, было бы более сложно реализовать.

4 голосов
/ 27 апреля 2020

Это на самом деле старое поведение, которое не исчезнет go. Ответ Томаса верен для старых FSI, но если вы установите что-то более новое (например, NET Core 3.1 latest или. NET 5 preview), вы увидите с dotnet fsi, что None форматирует как None с вашим примером.

...