Вариант использования Ruby для nil, эквивалентный Python None или JavaScript undefined - PullRequest
4 голосов
/ 07 октября 2010

Как Ruby's nil проявляется в коде?Например, в Python вы можете использовать None для аргумента по умолчанию, когда он ссылается на другой аргумент, но в Ruby вы можете ссылаться на другие аргументы в списке аргументов (см. этот вопрос ).В JS, undefined всплывает еще больше, потому что вы не можете указать аргументы по умолчанию вообще.Можете ли вы привести пример того, как всплывает RubyNone и как с этим справляются?

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

Ответы [ 5 ]

7 голосов
/ 07 октября 2010

Ruby's nil и Python None в значительной степени эквивалентны (они представляют отсутствие ценности), но люди, приезжающие из Python, могут обнаружить удивительное поведение. Во-первых, Ruby возвращает nil в ситуациях, когда Python вызывает исключение:

Доступ к массивам и хэшам:

[1, 2, 3][999] # nil. But [].fetch(0) raises an IndexError
{"a" => 1, "b" => 2}["nonexistent"] # nil. But {}.fetch("nonexistent") raises an IndexError

Переменные экземпляра экземпляра:

class MyClass
  def hello
    @thisdoesnotexist
  end
end

MyClass.new.hello #=> nil

Вторым замечательным фактом является то, что nil - это объект с множеством методов, вы даже можете преобразовать его в целое число, число с плавающей запятой или строку:

nil.to_i # 0
nil.to_f # 0.0 # But Integer(nil) or Float(nil) raise a TypeError.
nil.to_s # ""

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

Я не уверен, что это отвечает на ваш вопрос, только мои 2 цента.

2 голосов
/ 08 октября 2010

В дополнение ко всем объяснениям по поводу nil, ruby ​​также имеет «определено?».

a = nil

p defined?(a)  #=> "local-variable"
p a.nil?       #=> true
p defined?(b)  #=> nil
2 голосов
/ 07 октября 2010

Одним из вариантов использования nil, который вы часто видите в коде Ruby, является следующее:

a ||= 10 # or a = a || 10

Это работает, потому что, как только переменная была замечена в левой части присваивания, она неявно имеетзначение ноль

>> if false 
..   x = y
..   z
..   end
=> nil
>> x
=> nil
>> z
NameError: undefined local variable or method `z' for main:Object

Таким образом, когда часть a || 10 оценивается, она оценивается как nil || 10, что дает 10.

nil и false также являются единственными двумя значениями вРубины, которые являются логически ложными, поэтому обычно методы возвращают nil в случае сбоя.Существует гем под названием andand, который использует именно это, поэтому вместо чего-то вроде

@first_name &&= @first_name.trim

вы можете написать

@first_name.andand.trim

Это в основном переводится в трим @first_name, еслиимеет значение, отличное от nil, в противном случае оценивается как nil.Как вы можете себе представить, это особенно полезно при цепочечных методах, где один из посредников может потенциально вернуть nil.

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

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

0 голосов
/ 07 октября 2010

Они также используются вместо void: в статическом языке компилятор просто запрещает вам использовать возвращаемое значение функции void, но в динамическом языке каждая процедура должна возвращать что-то . Поэтому используется специальное значение nil.

0 голосов
/ 07 октября 2010

Мой Руби-фу очень слаб, но nil может быть тем, что вы ищете. Вот краткая иллюстрация использования nil в функции в качестве аргумента по умолчанию.

irb(main):003:0> def foo(a = nil)
irb(main):004:1> puts a
irb(main):005:1> end
=> nil
irb(main):006:0> foo(1)
1
=> nil
irb(main):007:0> foo()
nil
=> nil
irb(main):008:0> 
...