LINUX.ORG.RU

nil в языках программирования


0

1

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

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

К примеру в JavaScript есть есть два значения похожих на nil: null и undefined. (Нужно ли было плодить?)

В Scheme есть #f, но нет nil. В Factor тоже нету nil, и используют f. (Нужен ли nil если есть false?)

Кроме того, как-то читал что вроде в первых версиях Objective-C был объект nil (Objective-C не знаю вообще), который поглощал вызовы, был чёрной дырой. Т.е. вёл себя как NaN для чисел. На любое сообщение объект возвращал nil.

В треде приветствуются:

  • Ссылки на статьи с обзором различных подходов
  • Ссылки на какие-либо интересные языки, относящиеся к теме

UPD: Насколько допустимо трактовать «пустые» объекты (пустой список, пустой словарь и т.д.) как false, и есть ли у такой фичи опасные побочные эффекты, или вообще расположение к каким-либо багам.

★★

Последнее исправление: vladimir-vg (всего исправлений: 1)

или null как признак отсутствия объекта по ссылке что было еще в С как NULL указатель или монада maybe или кастумные нули для каждого класса (container.end например из stl) но вобщем все суть одного и того же а именно объект есть или его нету

bga_ ★★★★
()

из всех подходов типизированный null как С, C# или монадический лучшие потому что позволяют компилятору проанализировать код и ткнуть кодера в те места где он забыл проверку на нуль

bga_ ★★★★
()
Ответ на: комментарий от vladimir-vg

> Просто может можно было обойтись одним null-ом?

если ты действительно понимаешь, что это разные null-ы, то о каком вообще «обойтись одним null-ом» может идти речь? о_О

arsi ★★★★★
()
Ответ на: комментарий от arsi

> если ты действительно понимаешь, что это разные null-ы, то о каком вообще «обойтись одним null-ом» может идти речь? о_О

Вон в рубях при обращении к словарю по несуществующему ключу возвращается nil. Вполне годно. В js почему-то undefined.

Нафиг делать два разных nil-а?

vladimir-vg ★★
() автор топика
Ответ на: комментарий от vladimir-vg

вообще все верно. 2 нуля в js это чтобы различать _foo() и _foo(null) хотя от _foo(undefined) оно не спасет и на практике все пишут if(a == null) a = {} поэтому 2 нуля зря - достаточно одного null. кстати window.undefined = 1 усугубляет недоверие к undefined да и писать его длинно

bga_ ★★★★
()
Ответ на: комментарий от vladimir-vg

> Вон в рубях при обращении к словарю по несуществующему ключу возвращается nil. Вполне годно. В js почему-то undefined.

хз как в рубях, но в перле в хэшах тоже есть два «nil-а»: exists($a{$b}) — запись в %a с ключом $b вообще существует, и defined($a{$b}) — записи $a{$b} присвоено хоть какое-нибудь значение. разница огромная.

arsi ★★★★★
()
Ответ на: комментарий от vladimir-vg

>Вон в рубях при обращении к словарю по несуществующему ключу возвращается nil. Вполне годно.

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

yoghurt ★★★★★
()
Ответ на: комментарий от yoghurt

В Smalltalk кидается эксепшон, ну ты, наверно, знаешь

Не, я Smalltalk пока так и не осилил. Хотя идея нравится. Чуть позже.

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

if dict[:key]
  # blah-blah
end

заместо что-нибудь вроде

begin
  value = dict[:key]
  
  # blah-blah
rescue KeyError => e
  error
end

Да, похоже возвращать специальное значение вроде undefined это третий, удобный вариант.

vladimir-vg ★★
() автор топика
Ответ на: комментарий от bga_

> там пустой список?

В ирлонге вродеж символы есть, вот тебе и null/true/false

vladimir-vg ★★
() автор топика
Ответ на: комментарий от bga_

Например, если в словаре значение есть, возвращается кортеж {ok, Value}, если нет — то undefined или false. Но undefined и false — это обычные атомы. Другая функция может возвращать not_found, notfound или что-нибудь другое. Короче, специального значения нет, есть некоторое множество атомов, которые обычно используется.

undet
()
Ответ на: комментарий от yoghurt

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

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

cvb
()
Ответ на: комментарий от undet

вобщем те же яйца вид сбоку. имхо нулевость как префикс типа самое лучшее. можно писать var foo = bar[com] || default или забыть написать default и анализатор кода тебя ткнет носом

bga_ ★★★★
()
Ответ на: комментарий от vladimir-vg

В Racket в функцию hash-ref третьим параметром передается значение, которое будет возвращено в качестве результата, если для ключа в таблице не определено значение.

в CL возвращается два значения, примерно как undet выше написал

korvin_ ★★★★★
()

> Нужен ли nil если есть false?

В школу.

gandjubas
()
Ответ на: комментарий от vladimir-vg

>заместо что-нибудь вроде

Можно не ловить исключения, на то есть всякие #at:ifAbsent: и #at:ifAbsentPut: - первый метод в случае неудачи выполнит код в блоке (2й аргумент), второй метод положит значение блока (2й аргумент)

yoghurt ★★★★★
()
Ответ на: комментарий от cvb

>Не нужно гадать, у хешей рубиновых есть метод has_key?

Ага, который возвращает true или false. Т.е. сначала делаем поиск со сложностью (надеюсь) O(ln(n)) по хешу чтобы проверить, есть ли там ключ, и потом опять такой же O(ln(n)) - чтобы получить несчастное значение. Отлично, так держать :)

yoghurt ★★★★★
()
Ответ на: комментарий от yoghurt

если кешировать последний результат поиска то это невелируется :)

bga_ ★★★★
()
Ответ на: комментарий от yoghurt

Ага, который возвращает true или false. Т.е. сначала делаем поиск со сложностью (надеюсь) O(ln(n)) по хешу чтобы проверить, есть ли там ключ, и потом опять такой же O(ln(n)) - чтобы получить несчастное значение. Отлично, так держать :)

Решения, в которых используют хеши, наверное в 90%, не вызовут каких-либо нареканий, даже если сложность будет O(n^2) или того хуже, тк часто размеры хешей мизерны. Если же это всеже становится проблемой, то в руби есть fetch, который, о чудо, может кидаться ексепшеном, если ключа не оказалось, либо передать конструктору хеша блок, который будет вызывать нужный ексепшен. Так что нечего тут на руби гнать)

cvb
()

В Objective-C есть NULL это null-pointer из C и nil - это в принципе тоже null-pointer но на Objective-C объект. Они равны по значению, но семантика разная.

anonymous
()

>Objective-C
Он там до сих пор живее всех живых.

trex6 ★★★★★
()

> В Scheme есть #f, но нет nil

Это в CL есть #f, но нету nil (ну или наоборот - есть nil, но нету #f), а в scheme есть и #f и nil.

anonymous
()
Ответ на: комментарий от cvb

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

Ну хоть так. Я верил, что в руби не все так плохо :)

yoghurt ★★★★★
()
Ответ на: комментарий от Reset

А разве нет?

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

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

yoghurt ★★★★★
()
Ответ на: комментарий от yoghurt

> В CL есть t и nil.

Ну да, t и nil. А #f - нету, вместо него тот же nil.

anonymous
()
Ответ на: комментарий от yoghurt

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

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

anonymous
()
Ответ на: комментарий от vladimir-vg

Вон в рубях при обращении к словарю по несуществующему ключу возвращается nil. Вполне годно. В js почему-то undefined.

[offtop]это смотря как хеш создан[/offtop]

do0dlez ★★
()
Ответ на: комментарий от anonymous

>Ну, типа - можно реализовать мап в виде того же красно-черного дерева с логарифмической сложностью, а можно - в виде хеш-таблицы, с константной

В дереве данные всегда будут отсортированы. Хеш такого сервиса не предоставляет.

Absurd ★★★
()
Ответ на: комментарий от anonymous

> Это в CL есть #f, но нету nil (ну или наоборот - есть nil, но нету #f), а в scheme есть и #f и nil.

Я не буду писать комменты про предметы, в которых не разбираюсь. Я не буду писать комменты про предметы, в которых не разбираюсь. Я не буду писать комменты про предметы, в которых не разбираюсь.

anonymous
()
Ответ на: комментарий от Reset

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

yoghurt ★★★★★
()
Ответ на: комментарий от anonymous

В Схеме нет nil (есть null, это пустой список). #t и #f это другое вообще. В CL nil это отдельный символ, который можно использоваться в качестве схемовского #f. Пнятненько?

o
()
Ответ на: комментарий от anonymous
Welcome to Racket v5.1.1.
> (if '() 'true 'false)
true
;clisp
>(if '() 'true 'false)
FALSE
o
()

nil должен быть типизирован

Это все что от него требуется.

_________

//wfrr

anonymous
()
Ответ на: комментарий от vladimir-vg

Потмоу что в js нет словарей, там объекты.

_________

//wfrr

anonymous
()
Ответ на: комментарий от anonymous

> Соответствующий типу для которого он nil, не догадался да?

т.е. nil-ов на самом деле много. Для каждого типа свой отдельный экземляр nil.

А в чём профит?

vladimir-vg ★★
() автор топика
Ответ на: комментарий от vladimir-vg

Object d = getString() //d будет равен null setInt((Integer)d) //при null исключения не будет, еслиб null был бы типизированный, то было бы

_________

//wfrr

anonymous
()
Ответ на: комментарий от vladimir-vg

Object d = getString()

//d будет равен null

setInt((Integer)d)

//при null исключения не будет, еслиб null был бы типизированный, то было бы

_________

//wfrr

anonymous
()
Ответ на: комментарий от Absurd

> В дереве данные всегда будут отсортированы. Хеш такого сервиса не предоставляет.

Это к чему ты сказал?

anonymous
()
Ответ на: комментарий от o

> В Схеме нет nil (есть null, это пустой список). #t и #f это другое вообще. В CL nil это отдельный символ, который можно использоваться в качестве схемовского #f.

Ну да. В схеме есть пустой список (он же Nil, он же null) и #f, причем #f != `(), в CL есть пустой список (он же Nil), но нету #f, т.к. вместо него Nil.

anonymous
()
Ответ на: комментарий от anonymous

>Это к чему ты сказал?

Третью звезду хочу.

Absurd ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.