Почему процы могут вызываться с === в ruby ​​1.9?

В этой статье упоминается 4 способа вызова процедур в ruby ​​1.9, и === является одним из них. Я не понимаю, почему это было бы сделано так вообще. Имеет ли он какое-либо отношение к нормальному значению === (спрашивая, являются ли два объекта одним и тем же объектом)?

irb (основной):010:0> f =-> n {[: привет, n]}
=> #
irb(основной): 011: 0> f.call (: привет)
=> [: привет,: привет]
irb(основной):012:0> f ===: привет
=> [: привет,: привет]
irb(основной):013:0> Object.new === Object.new
=> ложь
irb (основной):014:0> f === f
=> [: привет, #]

4 ответа

Решение

Вот что должны сказать документы:

Это позволяет объекту proc быть целью when оговорка в материалах дела.

Это, возможно, надуманный пример:

even = proc { |x| x % 2 == 0 }
n = 3
case n
when even
  puts "even!"
else
  puts "odd!"
end

Это работает, потому что case/when в основном выполняется так:

if even === n
  puts "even!"
else
  puts "odd!"
end

case/when проверяет, какую ветку выполнить, вызвав === на аргументы when пункты, выбирая первое, которое возвращает истинное значение.

Несмотря на его сходство с оператором равенства (== это не более сильная или более слабая форма этого. Я пытаюсь думать о === оператор как оператор "принадлежит". Class определяет его так, что вы можете проверить, принадлежит ли объект классу (т.е. является экземпляром класса или подклассом класса), Range определяет его, чтобы проверить, принадлежит ли аргумент диапазону (то есть включен ли он в диапазон), и так далее. Это на самом деле не делает Proc case имеет больше смысла, но думайте о нем как об инструменте для создания своих собственных операторов, как в моем примере выше; Я определил объект, который может определить, принадлежит ли что-то множеству четных чисел.

Обратите внимание, что === в Ruby НЕ о равенстве, в отличие от JavaScript. Он специально используется для падежных выражений:

case cats.length
  when 42                         # Uses 42      === cats.length
    puts :uh
  when /cool/i                    # Uses /cool/i === cats.length
    puts :oh
  when ->(n){ n.odd? || n/3==6 }  # Passes cats.length to the proc
    puts :my
end

Эта функция полезна в случае построения, когда нужно что-то вычислить при сравнении.

is_odd  =-> n { n%2 != 0 }
is_even =-> n { n%2 == 0 }

case 5
when is_even
  puts "the number is even"
when is_odd
  puts "the number is odd"
end

=> the number is odd

Имеет ли он какое-либо отношение к нормальному значению === (спрашивая, являются ли два объекта одним и тем же объектом)?

На самом деле, это распространенное заблуждение о === в рубине. Это на самом деле не строго для Object#object_id сравнение (хотя таково его поведение во многих общих вызовах). В рубине === это случай погружения.

Вот описание === от Object: "Case Equality - для класса Object, фактически то же самое, что вызов #==, но обычно переопределяется потомками, чтобы обеспечить содержательную семантику в операторах case."

К сожалению, хотя он состоит из трех =, это не имеет ничего общего даже с равенством:-D

Другие вопросы по тегам