Подтвердить что ты не робот

Почему у нас нет двух нулей?

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

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

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

var apple;

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

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

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

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

4b9b3361

Ответ 1

В моем программировании я недавно принял практику дифференцирования "нулевого языка" и "нулевого домена".

"Нуль языка" - это специальное значение, предоставляемое языком программирования, для выражения того, что переменная имеет значение "no value". Это необходимо как фиктивное значение в структурах данных, списках параметров и возвращаемых значениях.

"Домен null" - это любое количество объектов, которые реализуют шаблон дизайна NullObject. На самом деле, у вас есть один отдельный нуль домена для каждого контекста домена.

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

Каждый раз, когда требуется нуль, спросите себя: это язык нуль или домен null?

Ответ 2

Не так ли плохо, что у нас есть один null?

Ответ 3

В большинстве языков программирования null означает "пустой" или "undefined". "Неизвестно", с другой стороны, что-то другое. По существу "неизвестный" описывает состояние объекта. Это состояние должно было произойти откуда-то в вашей программе.

Посмотрите на шаблон нулевого объекта. Это может помочь вам с тем, чего вы пытаетесь достичь.

Ответ 5

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

var apple = Apple.Unknown;
while (apple == Apple.Unknown) {} // etc

Ответ 6

Существование значения:

  • Python: vars().has_key('variableName')
  • PHP: isset(variable)
  • JavaScript: typeof(variable) != 'undefined'
  • Perl: (variable != undef) или, если хотите: (defined variable)

Конечно, когда переменная undefined, это не NULL

Ответ 7

Примечание null является приемлемым, но известным условием. Неизвестное состояние - это другое дело ИМО. Моя беседа с Дэном в разделе комментариев главного сообщения будет уточнять мою позицию. Спасибо Дэн!.

Что вы, вероятно, хотите запросить, является ли объект инициализирован или нет.

ActionScript имеет такую ​​вещь (null и undefined). Однако с некоторыми ограничениями.

См. документация:

тип данных void

Тип данных void содержит только одно значение, undefined. В предыдущих версиях ActionScript undefined было значением по умолчанию для экземпляров класса Object. В ActionScript 3.0 значение по умолчанию для экземпляров Object равно null. Если вы попытаетесь присвоить значение undefined экземпляру класса Object, Flash Player или Adobe AIR преобразует значение в значение null. Вы можете присваивать значение undefined переменным, которые являются нетипизированными. Необязательные переменные - это переменные, которые либо не имеют аннотаций какого-либо типа, либо используют символ звездочки (*) для аннотации типа. Вы можете использовать void только как аннотацию типа возвращаемого значения.

Ответ 8

Зачем останавливаться на двух?

Когда я брал базы данных в колледже, нам сказали, что кто-то (извините, не помните имя исследователя или статьи), посмотрел на кучу db-схем и обнаружил, что null имеет примерно 17 разных значений: "не знаю", "невозможно знать", "не применяется", "нет", "пусто", "действие не принято", "поле не используется" и т.д.

Ответ 9

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

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

Ответ 10

Некоторые люди будут утверждать, что мы должны избавиться от 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);
}

Ответ 11

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

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

if(isset($apple) && empty($apple))
{
    sulk();
}
else
{
    eatApple();
}

Ответ 12

Тип Null является подтипом всех ссылочных типов - вы можете использовать null вместо ссылки на любой тип объекта, что сильно ослабляет систему типов. Он считается одним из исторически плохая идея его создателем и существует только при проверке того, является ли адрес нулевым, его легко реализовать.

Ответ 13

Что касается того, почему у нас нет двух нулей, не связано ли это с тем, что исторически в C NULL был простым #define, а не отдельной частью языка вообще?

Ответ 14

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

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

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

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

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

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

Ответ 15

В 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 и Lither в один тип данных:)

Ответ 16

Пробовал: Visual Basic 6 имел Nothing, Null и Empty. И это привело к такому плохому коду, которое показало в № 12 в легендарной Тринадцати путях Loathe VB в статье доктора Доббса.

Используйте нулевой шаблон объекта, как это предполагали другие.

Ответ 18

boolean getAnswer() throws Mu

Ответ 19

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

Ответ 20

Я думаю, что один NULL является более низким общим знаменателем для работы с основным шаблоном

if thing is not NULL
  work with it
else
  do something else

В части "сделать что-то еще" есть широкий спектр возможностей: "хорошо, забудьте", пытаясь получить "вещь" в другом месте. Если вы не просто игнорируете что-то NULL, вам, вероятно, нужно знать, почему "вещь" была NULL. Имея несколько типов NULL, вы сможете ответить на этот вопрос, но возможные ответы многочисленны, как это намечено в других ответах здесь. Недостающая вещь может быть просто ошибкой, это может быть ошибка при попытке ее получить, она может быть недоступна прямо сейчас и так далее. Чтобы решить, какие случаи применяются к вашему коду, что означает, что вы должны их обрабатывать - это домен. Поэтому лучше использовать механизм, определенный приложением, для кодирования этих причин, а не для поиска языковой функции, которая пытается справиться со всеми из них.

Ответ 21

Это потому, что Null - это артефакт используемого вами языка, а не просто программист. Он описывает естественное состояние объекта в контексте, в котором он используется.

Ответ 22

Если вы используете .NET 3.0+ и вам нужно что-то еще, вы можете попробовать Maybe Monad. Вы можете создать любые типы "Maybe", которые вам нужны, и, используя синтаксис LINQ, выполните соответствующий процесс.

Ответ 23

AppleInformation appleInfo;    
while (appleInfo is null)
{
    askForAppleInfo();
}

Apple apple = appleInfo.apple;
if (apple is null)
{
    sulk();
}
else
{
    eatApple(apple);
}

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

Ответ 24

Для меня null означает отсутствие значения, и я пытаюсь использовать его только для представления этого. Конечно, вы можете дать нулевое значение, как вам нравится, так же, как вы можете использовать 0 или -1 для представления ошибок вместо их числовых значений. Однако предоставление различных значений одному представлению может быть неоднозначным, поэтому я бы не рекомендовал его.

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

Ответ 25

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

Например, это используется в коллекциях, которые позволяют элементам иметь значение null. Внутри они используют private static final Object UNSET = new Object, который используется как неустановленное значение и, таким образом, позволяет хранить null в коллекции. (Насколько я помню, инфраструктура Java-коллекции вызывает этот объект TOMBSTONE вместо UNSET. Или это была эта структура коллекции Smalltalk?)

Ответ 26

VB6

  • Ничего = > "Нет значения".
  • Null = > "Я не знаю, что такое значение" - так же, как DBNull.Value в .NET

Ответ 27

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

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

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

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