Dlaczego wykrzykniki są używane w metodach Ruby?

W Rubim niektóre metody mają znak zapytania (?), które zadają pytanie, takie jak include?, które pytają, czy dany obiekt jest dołączony, to zwraca true / false.

Ale dlaczego niektóre metody mają wykrzykniki (!) gdzie inne nie?

Co to znaczy?
Author: dreftymac, 2009-03-04

10 answers

Ogólnie metody, które kończą się na ! wskazują, że metodazmodyfikuje obiekt, na którym jest wywołana . Ruby nazywa je " niebezpiecznymi metodami ", ponieważ zmieniają stan, do którego ktoś inny może mieć odniesienie. Oto prosty przykład dla ciągów:

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

Wyświetli się:

a string

W standardowych bibliotekach jest wiele miejsc, w których zobaczysz pary podobnie nazwanych metod, jedna z ! i jedna bez. Te Bez są nazywane "bezpieczne metody" i zwracają kopię oryginału ze zmianami zastosowanymi do kopii , z bez zmian callee. Oto ten sam przykład bez !:

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

To wyjście:

A STRING
a string

Pamiętaj, że to tylko konwencja, ale wiele klas Ruby podąża za nią. Pomaga również śledzić to, co jest modyfikowane w kodzie.

 532
Author: tgamblin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-14 22:54:22

Wykrzyknik oznacza wiele rzeczy, a czasami nie można z niego wiele powiedzieć poza "to niebezpieczne, uważaj".

Jak mówili inni, w standardowych metodach jest często używany do wskazania metody, która powoduje mutację obiektu, ale nie zawsze. Zauważ, że wiele standardowych metod zmienia odbiornik i nie ma wykrzyknika (pop, shift, clear), niektóre metody z wykrzyknikami nie zmieniają odbiornika (exit!). Zobacz to Artykuł na przykład.

Inne biblioteki mogą używać go inaczej. W Rails wykrzyknik często oznacza, że metoda rzuci wyjątek na niepowodzenie, a nie po cichu.

To konwencja nazewnictwa, ale wiele osób używa jej w subtelny sposób. W Twoim kodzie dobrą zasadą kciuków jest używanie go zawsze, gdy jakaś metoda robi coś "niebezpiecznego", zwłaszcza gdy istnieją dwie metody o tej samej nazwie i jedna z nich jest bardziej" niebezpieczna " niż druga. "Niebezpieczny" może oznaczać prawie wszystko.
 125
Author: Brian Carper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-04 21:59:56

Ta konwencja nazewnictwa została zniesiona ze schematu .

1.3.5 konwencje nazewnictwa

Zgodnie z konwencją, nazwy procedur które zawsze zwracają wartość logiczną zazwyczaj kończy się `?''. Takie procedury są nazywane predykatami.

Zgodnie z konwencją, nazwy procedur które przechowują wartości w uprzednio przydzielone lokalizacje (patrz punkt 3.4) zazwyczaj kończy się `!''. Takie procedury nazywane są procedurami mutacji. Przez konwencja, wartość zwrócony przez a procedura mutacji jest nieokreślona.

 60
Author: Steven Huwig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-04 21:44:52

! zazwyczaj oznacza to, że metoda działa na obiekt zamiast zwracać wynik. Z książki Programowanie Ruby :

Metody, które są "niebezpieczne" lub modyfikują odbiornik, mogą być nazwane z końcówką "!".

 23
Author: Pesto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-18 05:08:02

Od themomorohoax.com:

Huk może być użyty w poniższy sposób, zgodnie z moimi osobistymi preferencjami.

1) Metoda active record powoduje błąd, jeśli metoda nie to, co mówi.

2) metoda active record zapisuje rekord lub metoda zapisuje obiekt (np. strip!)

3) metoda robi coś "ekstra", jak posty do jakiegoś miejsca, czy robi niezła akcja.

Chodzi o to, że używaj huku tylko wtedy, gdy naprawdę zastanawiałam się, czy jest to konieczne, aby zaoszczędzić innym programistom irytacji z konieczności sprawdź, dlaczego używasz huk.

The bang zapewnia dwa sygnały dla innych deweloperów.

1) że nie jest konieczne zapisywanie obiektu po wywołaniu metoda.

2) po wywołaniu metody, db zostanie zmieniony.

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

 14
Author: Edward Castaño,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-09 00:05:46

Najbardziej trafne jest stwierdzenie, że metody z hukiem! są bardziej niebezpieczne lub zaskakujące wersja. Istnieje wiele metod, które mutują bez huku, takich jak .destroy ogólnie rzecz biorąc, metody mają grzywkę tylko tam, gdzie istnieje bezpieczniejsza alternatywa w podstawowej lib.

Na przykład, w tablicy mamy .compact i .compact!, obie metody mutują tablicę, ale .compact! zwraca nil zamiast self, jeśli w tablicy nie ma nil, co jest bardziej zaskakujące niż zwracam siebie.

Jedyną metodą bez mutacji jaką znalazłem z hukiem jest Kernel's .exit! co jest bardziej zaskakujące niż .exit ponieważ nie można złapać SystemExit podczas zamykania procesu.

Rails i ActiveRecord kontynuują ten trend, ponieważ wykorzystują bang do bardziej "zaskakujących" efektów, takich jak .create! co powoduje błędy przy niepowodzeniu.

 14
Author: BookOfGreg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:11

Proste wyjaśnienie:

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.

Ale jeśli kiedykolwiek wywołałeś metodę downcase! w powyższym wyjaśnieniu, foo zmieniłbyś na downcase na stałe. downcase! nie zwróci nowego obiektu string, lecz zastąpi go, całkowicie zmieniając foo na downcase. Sugeruję nie używać downcase!, chyba że jest to całkowicie konieczne.

 6
Author: Mirage,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-15 22:47:43

Nazywane "destrukcyjnymi metodami" mają tendencję do zmiany oryginalnej kopii obiektu, do którego się odnosisz.

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
Author: Mittinti Ramana Murthy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 14:43:20

Bottom line: ! metody po prostu zmieniają wartość obiektu, do którego są wywołane, podczas gdy metoda bez ! zwraca manipulowaną wartość bez zapisu nad obiektem, do którego została wywołana metoda.

Używaj tylko !, Jeśli nie planujesz potrzebować oryginalnej wartości przechowywanej w zmiennej, na której wywołałeś metodę.

Wolę robić coś takiego:

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

Lub

foo = "word"
puts foo.capitalize

Zamiast

foo = "word"
foo.capitalize!
puts foo

Na wszelki wypadek chciałbym uzyskać dostęp do oryginału znowu wartość.

 0
Author: Charles,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-23 21:10:59
!
Lubię myśleć o tym jako o wybuchowej zmianie, która niszczy wszystko, co było wcześniej. Bang lub wykrzyknik oznacza, że dokonujesz trwałej zapisanej zmiany w kodzie.

Jeśli użyjesz na przykład metody Ruby do globalnego substytucji gsub! zastąpienie, które wykonasz, jest trwałe.

Innym sposobem, który możesz sobie wyobrazić, jest otwarcie pliku tekstowego i wykonanie find and replace, a następnie zapisanie. ! robi to samo w Twoim kodzie.

Kolejne przydatne przypomnienie, jeśli pochodzisz ze świata bash jest sed -i ma podobny efekt dokonywania trwałych zapisanych zmian.

 0
Author: Charlie Wood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-03 15:16:07