Почему у нас нет двух нулей?
Я часто задавался вопросом, почему языки с null
, представляющие "нет значения", не делают различий между пассивным "Я не знаю, что такое значение" и более напористым "Нет значения".
Было несколько случаев, когда мне хотелось бы провести различие между ними (особенно при работе с пользовательскими вводами и базами данных).
Я представляю себе следующее, где мы называем два состояния unknown
и null
:
var apple;
while (apple is unknown)
{
askForApple();
}
if (apple is null)
{
sulk();
}
else
{
eatApple(apple);
}
Очевидно, что мы можем уйти без него, вручную сохраняя состояние somwhere else, но мы можем сделать это и для нулей.
Итак, если мы можем иметь один null
, почему мы не можем иметь два?
Ответы
Ответ 1
В моем программировании я недавно принял практику дифференцирования "нулевого языка" и "нулевого домена".
"Нуль языка" - это специальное значение, предоставляемое языком программирования, для выражения того, что переменная имеет значение "no value". Это необходимо как фиктивное значение в структурах данных, списках параметров и возвращаемых значениях.
"Домен null" - это любое количество объектов, которые реализуют шаблон дизайна NullObject. На самом деле, у вас есть один отдельный нуль домена для каждого контекста домена.
Для программистов довольно часто использовать нуль языка как null, но я обнаружил, что он имеет тенденцию делать код более процедурным (менее объектно-ориентированным), а намерение усложнять.
Каждый раз, когда требуется нуль, спросите себя: это язык нуль или домен null?
Ответ 2
Не так ли плохо, что у нас есть один null?
Ответ 3
В большинстве языков программирования null означает "пустой" или "undefined". "Неизвестно", с другой стороны, что-то другое. По существу "неизвестный" описывает состояние объекта. Это состояние должно было произойти откуда-то в вашей программе.
Посмотрите на шаблон нулевого объекта. Это может помочь вам с тем, чего вы пытаетесь достичь.
Ответ 4
javascript фактически имеет как null, так и undefined (http://www.w3schools.com/jsref/jsref_undefined.asp), но многие другие языки этого не делают.
Ответ 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 в статье доктора Доббса.
Используйте нулевой шаблон объекта, как это предполагали другие.
Ответ 17
Некоторые люди уже на шаг впереди вас.;)
Ответ 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: этот домен имеет нулевые бит информации.
- 'Пустой: это правильно не содержит данных в этом случае, например, в последний раз, когда шины были повернуты на новом автомобиле'
- 'Несколько, каскадные нули: например, расширение цены количества, когда никакое количество не может быть указано раз количество, которое не было указано пользователем в любом случае'
И вашему конкретному домену может потребоваться множество других значений "вне диапазона". Действительно, эти значения находятся в домене и в каждом случае должны иметь четко определенный смысл. (эрго, бесконечность действительно равна нулю)