Почему восклицательные знаки используются в методах Ruby? - PullRequest
497 голосов
/ 04 марта 2009

В Ruby некоторые методы имеют вопросительный знак (?), который задает вопрос, такой как include?, который спрашивает, включен ли рассматриваемый объект, затем возвращает true / false.

Но почему некоторые методы имеют восклицательные знаки (!), а другие нет?

Что это значит?

Ответы [ 10 ]

573 голосов
/ 04 марта 2009

Как правило, методы, оканчивающиеся на !, указывают, что метод изменит объект, для которого он вызван . Ruby называет их « опасными методами », потому что они изменяют состояние, на которое может ссылаться кто-то другой. Вот простой пример для строк:

foo = "A STRING"  # a string called foo
foo.downcase!     # modifies foo itself
puts foo          # prints modified foo

Будет выведено:

a string

В стандартных библиотеках есть много мест, где вы увидите пары методов с одинаковыми именами, один с !, а другой без. Те, у кого нет, называются «безопасными методами», и они возвращают копию оригинала с изменениями, примененными к копии , с вызываемым абонентом без изменений. Вот тот же пример без !:

foo = "A STRING"    # a string called foo
bar = foo.downcase  # doesn't modify foo; returns a modified string
puts foo            # prints unchanged foo
puts bar            # prints newly created bar

Это выводит:

A STRING
a string

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

130 голосов
/ 05 марта 2009

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

Как уже говорили другие, в стандартных методах он часто используется для обозначения метода, который заставляет объект мутировать сам, но не всегда. Обратите внимание, что многие стандартные методы меняют свой получатель и не имеют восклицательного знака (pop, shift, clear), а некоторые методы с восклицательным знаком не меняют своего получателя (exit!). См. эту статью , например.

Другие библиотеки могут использовать его по-другому. В Rails восклицательный знак часто означает, что метод будет генерировать исключение при сбое, а не молча.

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

70 голосов
/ 05 марта 2009

Это соглашение об именах взято из Схема .

1.3.5 Соглашения об именах

По договоренности, названия процедур которые всегда возвращают логическое значение обычно заканчиваются на ``? ''. Такие процедуры называются предикатами.

По соглашению, названия процедур которые хранят значения в ранее выделенные места (см. раздел 3.4) обычно заканчиваются на ``! ''. Такие процедуры называются процедуры мутации. От соглашение, значение, возвращаемое процедура мутации не указана.

23 голосов
/ 04 марта 2009

! обычно означает, что метод воздействует на объект, а не возвращает результат. Из книги Программирование на Ruby :

Методы, которые «опасны» или модифицируют получателя, могут быть названы завершающим «!».

16 голосов
/ 16 февраля 2014

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

Например, в Array у нас есть .compact и .compact!, оба метода мутируют массив, но .compact! возвращает nil вместо self, если в массиве нет nil, что более удивительно, чем просто возвращение self .

Единственный немутантный метод, который я нашел с ударом, это Kernel '.exit!, что более удивительно, чем .exit, потому что вы не можете поймать SystemExit, пока процесс закрытие.

Rails и ActiveRecord продолжают эту тенденцию, поскольку используют взрыв для более «удивительных» эффектов, таких как .create!, что вызывает ошибки при сбое.

16 голосов
/ 09 сентября 2011

От themomorohoax.com:

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

1) Метод активной записи вызывает ошибку, если метод не делает что он говорит, что будет.

2) Метод активной записи сохраняет запись или метод сохраняет объект (например, полоса!)

3) Метод делает что-то «лишнее», например, отправляет сообщения в другое место или делает какое-то действие.

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

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

1) что нет необходимости сохранять объект после вызова способ.

2) при вызове метода БД будет изменена.

http://www.themomorohoax.com/2009/02/11/when-to-use-a-bang-exclamation-point-after-rails-methods

6 голосов
/ 14 сентября 2013

Простое объяснение:

foo = "BEST DAY EVER" #assign a string to variable foo.

=> foo.downcase #call method downcase, this is without any exclamation.

"best day ever"  #returns the result in downcase, but no change in value of foo.

=> foo #call the variable foo now.

"BEST DAY EVER" #variable is unchanged.

=> foo.downcase! #call destructive version.

=> foo #call the variable foo now.

"best day ever" #variable has been mutated in place.

Но если бы вы когда-либо вызывали метод downcase! в приведенном выше объяснении, foo изменится на downcase навсегда downcase! не будет возвращать новый строковый объект, но заменит строку на месте, полностью изменив foo на нижний регистр. Я предлагаю вам не использовать downcase!, если это не является абсолютно необходимым.

1 голос
/ 23 мая 2017

Называется "Деструктивные методы". Они имеют тенденцию изменять оригинальную копию объекта, на который вы ссылаетесь.

numbers=[1,0,10,5,8]
numbers.collect{|n| puts n*2} # would multiply each number by two
numbers #returns the same original copy
numbers.collect!{|n| puts n*2} # would multiply each number by two and destructs the original copy from the array
numbers   # returns [nil,nil,nil,nil,nil]
1 голос
/ 03 апреля 2017
!

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

Если вы используете, например, метод Ruby для глобальной замены gsub!, то сделанная вами замена является постоянной.

Еще один способ представить это - открыть текстовый файл и выполнить поиск и замену с последующим сохранением. ! делает то же самое в вашем коде.

Другое полезное напоминание, если вы пришли из мира bash: sed -i имеет такой же эффект внесения постоянных сохраненных изменений.

0 голосов
/ 24 июля 2015

Итог: ! методы просто изменяют значение объекта, к которому они обращаются, тогда как метод без ! возвращает манипулируемое значение без записи поверх объекта, к которому был вызван метод.

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

Я предпочитаю делать что-то вроде:

foo = "word"
bar = foo.capitalize
puts bar

OR

foo = "word"
puts foo.capitalize

Вместо

foo = "word"
foo.capitalize!
puts foo

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

...