Какова цель нуля? - PullRequest
       58

Какова цель нуля?

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

Я учусь в классе компиляторов, и перед нами стоит задача создания собственного языка с нуля. В настоящее время наша дилемма заключается в том, включать ли тип 'null' или нет. Какую цель дает нуль? Некоторые из нашей команды утверждают, что в этом нет особой необходимости, в то время как другие являются ненулевыми только за дополнительную гибкость, которую она может обеспечить.

Есть ли у вас какие-либо мысли, особенно за или против нуля? Вы когда-нибудь создавали функциональность, которая требовала null?

Ответы [ 25 ]

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

Ноль не является ошибкой. Ноль означает «я пока не знаю»

Для примитивов вам на самом деле не нужен ноль (я должен сказать, что строки (в .NET) не должны его получать ИМХО)

Но для составных объектов это определенно служит цели.

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

Рассмотрим примеры C и Java, например. В C соглашение состоит в том, что нулевой указатель является нулевым числовым значением. Конечно, на самом деле это просто соглашение: ничто в языке не рассматривает эту ценность как нечто особенное. В Java, однако, null - это отдельная концепция, которую вы можете обнаружить и узнать, что да, это на самом деле плохая ссылка, и я не должен пытаться открыть эту дверь, чтобы увидеть, что находится на другой стороне.

Несмотря на это, я ненавижу нули почти хуже, чем что-либо еще.

РАЗЪЯСНЕНИЕ на основе комментариев: я ненавижу значение нулевого указателя defacto хуже нуля, чем я ненавижу null.

Каждый раз, когда я вижу назначение на null, я думаю: «О, хорошо, кто-то только что поставил мину в код. Когда-нибудь мы будем идти по связанному пути выполнения и BOOM ! NullPointerException! "

Я бы предпочел, чтобы кто-то указал полезное значение по умолчанию или NullObject, который позволяет мне знать, что «для этого параметра не установлено ничего полезного». Лысый ноль сам по себе является просто проблемой, ожидающей, чтобы это произошло.

Тем не менее, это все же лучше, чем необработанный ноль, блуждающий свободно.

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

Вы можете думать о любом типе как о наборе вместе с набором операций. Во многих случаях удобно иметь значение, которое не является «нормальным» значением; например, рассмотрим значение «EOF». для C getline(). Вы можете справиться с этим одним из нескольких способов: вы можете иметь значение NULL вне набора, вы можете отличить определенное значение от нуля (в C ((void *)0) может служить этой цели) или у вас может быть способ создания нового значения. тип, так что для типа T вы создаете тип T ' = def {T & cup; NULL} , как это делает Haskell (тип «Возможно»).

Какой из них лучше, тем лучше для множества приятных споров.

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

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

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

Кроме того, нулевой символ в строке переменной длины в стиле C используется для обозначения конца строки.

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

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

Ноль - не проблема - все, кто трактует и интерпретирует ноль по-разному, являются проблемой.

Мне нравится ноль. Если бы не было null, то null можно было бы заменить другим способом, чтобы код сказал: «Понятия не имею, чувак!» (что некоторые пишут: «У меня нет понятия, чувак!» или «У меня нет понятия, старый боб!» и т. д., и поэтому у нас снова будут точно такие же проблемы).

Я обобщаю, я знаю.

3 голосов
/ 26 февраля 2009

Практический пример нулевого значения - когда вы задаете вопрос «да / нет» и не получаете ответа. Вы не хотите использовать значение по умолчанию «нет», потому что может быть важно знать, что на вопрос не ответили в ситуациях, когда ответ очень важен.

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

Какую цель обеспечивает нуль?

Я полагаю, что здесь работают две концепции нуля.

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

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

Есть ли у вас какие-либо мысли, особенно за или против нуля?

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

Итог, все зависит от целей вашего языка:

  1. целевая аудитория программирования
  2. надежность
  3. производительности
  4. и т.д ...

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

BB

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

Еще один способ взглянуть на ноль - это проблема с производительностью. Если у вас есть сложный объект, содержащий другие сложные объекты и т. Д., То более эффективно разрешить всем свойствам изначально обнуляться, а не создавать какие-то пустые объекты, которые ни к чему не приведут и скоро будут заменены.

Это только одна перспектива, о которой я не мог упомянуть ранее.

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

Это решение зависит от цели языка программирования.

Для кого вы разрабатываете язык программирования? Вы проектируете это для людей, которые знакомы с производными от c языками? Если это так, то вам, вероятно, следует добавить поддержку null.

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

Взять блоки переключателей в C # в качестве примера. Все метки регистра в C # должны иметь явное выражение потока управления в каждой ветви. То есть все они должны заканчиваться либо оператором "break", либо явным переходом. Это означает, что в то время как этот код является законным:

switch(x)
{
    case 1:
    case 2:
        foo;
        break;
}

что этот код не будет законным:

switch (x)
{
    case 1:
        foo();
    case 2:
        bar();
        break;
}

Чтобы создать «провал» из случая 1 в случай 2, необходимо вставить переход, например:

switch (x)
{
    case 1:
        foo();
        goto case 2;
    case 2:
        bar();
        break;
}

Возможно, это что-то, что может нарушить ожидания программистов на C ++, использующих C #. Однако добавление этого ограничения служит цели. Это исключает возможность появления целого класса распространенных ошибок C ++. Это немного увеличивает кривую изучения языка, но в результате программист получает чистую выгоду.

Если ваша цель - разработать язык, предназначенный для программистов на C ++, то удаление нуля, вероятно, нарушит их ожидания. Это приведет к путанице и сделает ваш язык более трудным для изучения. Тогда ключевой вопрос: «какую выгоду они получают»? Или, в качестве альтернативы, «какой вред это причиняет».

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

Итак, резюмируя, я бы сказал, что вы должны:

  1. Определите ваши цели в создании языка. Для кого предназначен язык, и каковы их потребности.
  2. Принимайте решение на основе того, что помогает целевым пользователям наилучшим образом достичь своих целей.

Обычно это достаточно ясно дает желаемый результат.

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

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

Использовать шаблон нулевого объекта!

Если ваш язык является объектно-ориентированным, пусть у него есть класс UndefinedValue, в котором существует только один экземпляр-одиночка. Затем используйте этот экземпляр везде, где используется null. Преимущество этого в том, что ваш null будет отвечать на такие сообщения, как #toString и #equals. Вы никогда не встретите исключение нулевого указателя, как в Java. (Конечно, это требует, чтобы ваш язык был динамически набран).

...