web-dev-qa-db-fra.com

Pourquoi les points d'exclamation sont-ils utilisés dans les méthodes Ruby?

Dans Ruby, certaines méthodes ont un point d'interrogation (?) qui pose une question telle que include? qui demande si l'objet en question est inclus, le résultat est alors vrai/faux.

Mais pourquoi certaines méthodes ont-elles des points d'exclamation (!) alors que d'autres n'en ont pas?

Qu'est-ce que ça veut dire?

505
Lennie

En général, les méthodes qui se terminent par ! indiquent que la méthode va modifier l'objet sur lequel elle est appelée. Ruby les appelle "méthodes dangereuses" car ils modifient l'état auquel une autre personne pourrait avoir une référence. Voici un exemple simple pour les chaînes:

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

Cela produira:

a string

Dans les bibliothèques standard, il existe de nombreux endroits où vous verrez des paires de méthodes portant le même nom, l'une avec le ! et l'autre sans. Ceux qui n'en ont pas s'appellent des "méthodes sûres", et ils renvoient une copie de l'original avec les modifications appliquées à la copie, avec l'appelé non modifié. Voici le même exemple sans le !:

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

Cela génère:

A STRING
a string

Gardez à l'esprit qu'il ne s'agit que d'une convention, mais de nombreuses classes Ruby la suivent. Cela vous aide également à garder une trace de ce qui est modifié dans votre code.

579
Todd Gamblin

Le point d'exclamation signifie beaucoup de choses, et parfois vous ne pouvez pas en dire plus que "c'est dangereux, soyez prudent".

Comme d'autres l'ont dit, dans les méthodes standard, il est souvent utilisé pour indiquer une méthode qui provoque la mutation d'un objet, mais pas toujours. Notez que de nombreuses méthodes standard changent de destinataire et n’ont pas de point d’exclamation (pop, shift, clear), et certaines méthodes avec des points d’exclamation ne changent pas de récepteur (exit!). Voir cet article par exemple.

D'autres bibliothèques peuvent l'utiliser différemment. Dans Rails, un point d'exclamation signifie souvent que la méthode lève une exception en cas d'échec plutôt que d'échouer en silence.

C'est une convention de nommage, mais beaucoup de gens l'utilisent de manière légèrement différente. Dans votre propre code, une bonne règle empirique consiste à l’utiliser chaque fois qu’une méthode fait quelque chose de "dangereux", en particulier lorsque deux méthodes portant le même nom existent et que l’une est plus "dangereuse" que l’autre. "Dangereux" peut signifier presque n'importe quoi cependant.

132
Brian Carper

Cette convention de dénomination est levée de Scheme .

1.3.5 Conventions de dénomination

Par convention, les noms de procédures qui retournent toujours une valeur booléenne se terminent généralement par "? Ces procédures sont appelées prédicats.

Par convention, les noms de procédures qui stockent des valeurs dans des emplacements précédemment alloués (voir la section 3.4) se terminent généralement par "! Ces procédures sont appelées procédures de mutation. Par convention, la valeur renvoyée par une procédure de mutation n'est pas spécifiée.

71
Steven Huwig

! signifie généralement que la méthode agit sur l'objet au lieu de renvoyer un résultat. Extrait du livre Programming Ruby :

Les méthodes qui sont "dangereuses" ou qui modifient le récepteur peuvent être nommées avec un "!" De fin.

24
Pesto

Il est plus exact de dire que les méthodes avec un Bang! sont les plus dangereuses ou versions surprenantes . Il y a beaucoup de méthodes qui muent sans Bang, telles que .destroy et en général, les méthodes ont seulement une frange où une alternative plus sûre existe dans la bibliothèque principale .

Par exemple, sur Array, nous avons _.compact_ et _.compact!_, les deux méthodes mutent le tableau, mais _.compact!_ renvoie nil au lieu de self s'il n'y a pas de nil dans le tableau, ce qui est plus surprenant que je rentre tout simplement.

La seule méthode non mutante que j'ai trouvée avec une détonation est celle de Kernel.exit! , ce qui est plus surprenant que _.exit_ parce que vous ne pouvez pas attraper SystemExit pendant la fermeture du processus.

Rails et ActiveRecord poursuivent cette tendance en ce sens qu’ils utilisent bang pour créer des effets plus "surprenants" comme .create! , ce qui entraîne des erreurs en cas d’échec.

18
BookOfGreg

De themomorohoax.com:

Un coup peut être utilisé de la manière ci-dessous, dans l'ordre de mes préférences personnelles.

1) Une méthode d'enregistrement active génère une erreur si la méthode ne fait pas ce qu'elle dit.

2) Une méthode d'enregistrement actif enregistre l'enregistrement ou une méthode enregistre un objet (par exemple, une bande!)

3) Une méthode fait quelque chose d’extra, comme envoyer des messages à un endroit quelconque, ou effectue une action.

Le fait est que vous ne devez utiliser un bang que lorsque vous vous êtes vraiment demandé si cela était nécessaire, pour éviter aux autres développeurs de ne plus avoir à vérifier pourquoi vous utilisez un bang.

Le bang fournit deux indices aux autres développeurs.

1) qu’il n’est pas nécessaire de sauvegarder l’objet après avoir appelé la méthode.

2) lorsque vous appelez la méthode, la base de données va être modifiée.

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

16
Edward Castaño

Explication simple:

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.

Mais si vous avez déjà appelé une méthode downcase! dans l'explication ci-dessus, foo deviendrait downcase de manière permanente. downcase! ne renverrait pas un nouvel objet de chaîne mais remplacerait la chaîne en place, changeant totalement le foo en downcase. Je suggère que vous n'utilisiez pas downcase! à moins que ce ne soit absolument nécessaire.

6
Mirage

Appelées "méthodes destructives" Elles ont tendance à changer la copie originale de l'objet auquel vous faites référence.

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]
!

J'aime penser à cela comme à un changement explosif qui détruit tout ce qui s'est passé avant. Déclenchement ou point d'exclamation signifie que vous apportez une modification enregistrée permanente à votre code.

Si vous utilisez par exemple la méthode de Ruby pour la substitution globalegsub!, la substitution que vous effectuez est permanente.

Une autre façon de l’imaginer, c’est d’ouvrir un fichier texte et de rechercher, remplacer, puis de sauvegarder. ! fait la même chose dans votre code.

Un autre rappel utile, si vous venez du monde bash, est sed -i a le même effet de créer des modifications enregistrées de manière permanente.

1
Charlie Wood

Ligne de fond: les méthodes ! ne modifient que la valeur de l'objet sur lequel elles sont appelées, alors qu'une méthode sans ! renvoie une valeur manipulée sans écrire sur l'objet sur lequel la méthode a été appelée.

Utilisez uniquement ! si vous prévoyez de ne pas avoir besoin de la valeur d'origine stockée dans la variable sur laquelle vous avez appelé la méthode.

Je préfère faire quelque chose comme:

foo = "Word"
bar = foo.capitalize
puts bar

OR

foo = "Word"
puts foo.capitalize

Au lieu de

foo = "Word"
foo.capitalize!
puts foo

Juste au cas où je voudrais accéder à la valeur d'origine à nouveau.

0
Charles