Почему у нас нет двух нулей? - PullRequest
30 голосов
/ 25 февраля 2009

Я часто задавался вопросом, почему языки с null, представляющими "нет значения" , не делают различий между пассивными "Я не знаю, что такое значение" и более напористый «Нет значения.» .

Было несколько случаев, когда я хотел бы провести различие между ними (особенно при работе с пользовательским вводом и базами данных).

Я представляю себе следующее, где мы называем два состояния unknown и null:

var apple;

while (apple is unknown)
{
    askForApple();
}

if (apple is null)
{
    sulk();
}
else
{
    eatApple(apple);
}

Очевидно, что мы можем обойтись без него, вручную сохраняя состояние в другом месте, , но мы можем сделать это и для нулей .

Итак, если у нас может быть один null, почему у нас не может быть двух?

Ответы [ 27 ]

2 голосов
/ 25 февраля 2009

В PHP Strict вам нужно выполнить isset() проверку на наличие установленных переменных (иначе выдается предупреждение)

if(!isset($apple))
{
    askForApple();
}

if(isset($apple) && empty($apple))
{
    sulk();
}
else
{
    eatApple();
}
2 голосов
/ 25 февраля 2009

Некоторые люди будут утверждать, что мы должны избавиться от null в целом , что кажется вполне допустимым. В конце концов, зачем останавливаться на двух нулях? Почему бы не три или четыре и так далее, каждый из которых представляет состояние "нет значения" ?

Представьте себе это, с refused, null, invalid:

var apple;

while (apple is refused)
{
    askForApple();
}

if (apple is null)
{
    sulk();
}
else if(apple is invalid)
{
    discard();
}
else
{
    eatApple(apple);
}
2 голосов
/ 25 февраля 2009

Проблема в том, что в строго типизированном языке эти дополнительные нули должны содержать конкретную информацию о типе.

По сути, ваш дополнительный ноль - это метаинформация, метаинформация, которая может зависеть от типа.

Некоторые типы значений имеют эту дополнительную информацию, например, многие числовые типы имеют константу NaN.

В динамически типизированном языке вы должны учитывать разницу между ссылкой без значения (null) и переменной, где типом может быть что угодно (неизвестный или неопределенный)

Так, например, в статически типизированном C # переменная типа String может иметь значение null, поскольку это ссылочный тип. Переменная типа Int32 не может, потому что это тип значения, она не может быть нулевой. Мы всегда знаем тип.

В динамически типизированном Javascript тип переменной можно оставить неопределенным, и в этом случае необходимо различие между пустой ссылкой и неопределенным значением.

2 голосов
/ 25 февраля 2009

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

Проблема остается, однако, для ссылочных типов. Поскольку в .net нет указателей (по крайней мере, в «безопасных» блоках), «object? O» не скомпилируется.

2 голосов
/ 25 февраля 2009

В haskell вы можете определить что-то вроде этого:

data MaybeEither a b = Object a
                     | Unknown b
                     | Null
                       deriving Eq
main = let x = Object 5 in
       if x == (Unknown [2]) then putStrLn ":-("
       else putStrLn ":-)"

Идея состоит в том, что неизвестные значения содержат некоторые данные типа b, которые могут преобразовать их в известные значения (как это сделать зависит от конкретных типов a и b).

Внимательный читатель заметит, что я просто объединяю Maybe и Either в один тип данных:)

2 голосов
/ 28 февраля 2009

Это было опробовано: в Visual Basic 6 было ничего, пусто и пусто. И это привело к такому плохому коду, что он занял 12 место в легендарной статье Тринадцать способов ненавидеть В.Б. в Dr Dobbs.

Вместо этого используйте шаблон Null Object , как предлагали другие.

1 голос
/ 03 марта 2009

Учитывая, сколько времени понадобилось западной философии, чтобы понять, как можно говорить о понятии «ничто» ... Да, я не слишком удивлен, что это различие пропустили некоторое время.

1 голос
/ 26 февраля 2009
boolean getAnswer() throws Mu
1 голос
/ 25 февраля 2009

Некоторые люди уже на шаг впереди вас. ;)

0 голосов
/ 03 марта 2009

Два нуля - самый неправильный ответ. Если одного ноля недостаточно, вам нужны бесконечные нули.

Null Может означать:

  • Uninitialized '
  • 'Пользователь не указал'
  • «Не применимо здесь, цвет автомобиля до его покраски»
  • 'Unity: этот домен содержит ноль битов информации.'
  • 'Пусто: в этом случае правильно не хранятся данные, например, когда в последний раз колеса были повернуты на новом автомобиле'
  • 'Несколько, каскадные нули: например, расширение количественной цены, когда количество не может быть указано, если количество не задано пользователем в любом случае'

А вашему конкретному домену могут потребоваться многие другие виды внеполосных значений. Действительно, эти значения находятся в домене и должны иметь четко определенное значение в каждом случае. (следовательно, бесконечность действительно равна нулю)

...