Является ли выражение! Foo = допустимым в Ruby? - PullRequest
3 голосов
/ 02 апреля 2012

Примечание: я не совсем уверен, как назвать вопрос, поэтому, если у кого-то есть идея получше, отредактируйте его.

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

Этот код:

!foo = true

генерирует это предупреждение

warning: found = in conditional, should be ==

Я бы понял, если бы это произошло после if или unless заявления, но это не могло быть дальше от них (преувеличение). Я понимаю, что могу использовать:

foo = true
!foo

Полагаю, предупреждение не имеет большого значения, но немного раздражает то, что Руби полагает, что я делаю что-то не так - когда я не так.


Вопросы:

  • Это ошибка?
  • Можно ли отключить предупреждение?

Спасибо!

Ответы [ 5 ]

10 голосов
/ 02 апреля 2012

Это законно. Не ошибка. Предупреждение может быть подавлено .

Вы можете отключить предупреждение с помощью:

$VERBOSE = nil

Интересно, $VERBOSE - это случай, когда установка чего-то на false делает что-то иное, чем установка на nil.

Кстати, другие ответы, по крайней мере на начальном этапе, предполагают, что Ruby анализирует выражение как

(!foo) = true

... но это не тот случай. Он анализируется как:

!(foo = true)

... и он делает именно то, что хотел ОП. И нет никакой спецификации или ратифицированного стандарта для Ruby, поэтому, если он работает в MRI (эталонная реализация), то это законно.

4 голосов
/ 02 апреля 2012

Это всего лишь предупреждение и оценивается, как вы ожидаете.Вы можете временно отключить предупреждения, назначив $ VERBOSE = nil.

save_verbose, $VERBOSE = $VERBOSE, nil
result = !foo = true
$VERBOSE = save_verbos
result

Другие места в сети , предложив сделать вспомогательный метод ala

module Kernel
  def silence_warnings
    with_warnings(nil) { yield }
  end

  def with_warnings(flag)
    old_verbose, $VERBOSE = $VERBOSE, flag
    yield
  ensure
    $VERBOSE = old_verbose
  end
end unless Kernel.respond_to? :silence_warnings

Но,Я только что попробовал это в 1.9.2 и 1.8.7, и это было неэффективно при подавлении «предупреждение: найдено = в условном, должно быть ==»

4 голосов
/ 02 апреля 2012

Как уже предлагалось в предыдущих ответах, делать то, что вы хотите, недопустимо.

!foo = true

оценивается как

!(foo = true)

То есть присваивать truefoo и получите отрицание результата этого назначения, которое сводится к

!true

или

false

Если вы хотите сохранить !true, оно должно быть

foo = !true

Если вы хотите присвоить true для foo и отрицание для другой переменной, это будет

foo2 = !(foo = true)

, и это все равно вызовет предупреждение, потому что в конце концов этоназначение в условном выражении.

Я на самом деле хочу присвоить true для foo, а затем получить противоположность foo в стеке

Не имеет особого смысла,Вы «получаете что-то в стеке», присваивая это переменной, как foo2 в моем примере.

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

1 голос
/ 02 апреля 2012

Это ошибка в вашем коде:

!var = anything

Неверно.Вы пытаетесь присвоить либо TrueClass, либо FalseClass, что (вероятно) и возвращает !var.

Вы хотите:

!var == true

Теперь вы делаетесравнение (хотя и ненужное).

1 голос
/ 02 апреля 2012

Это технически неверное назначение левой руки. Вы хотите

foo =! True

Вы не можете присвоить значение противоположному объекту. Что не фу? =)

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