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 comme include? qui demande si l'objet en question est inclus, cela renvoie alors un vrai/faux.

mais pourquoi certaines méthodes ont des points d'exclamation ( ! ) alors que d'autres ne le font pas?

ça veut dire Quoi?

451
demandé sur dreftymac 2009-03-04 23:02:28

10 réponses

en général, les méthodes qui se terminent par ! indiquent que la méthode modifiera l'objet qu'elle appelle . Ruby les appelle méthodes dangereuses " parce qu'ils changent d'état que quelqu'un d'autre pourrait avoir une référence. Voici un exemple simple pour les cordes:

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

cette sortie sera:

a string

dans les bibliothèques standard, il y a beaucoup d'endroits où vous pouvez voir des paires des méthodes nommées de la même façon, une avec le ! et une Sans. Ceux Sans sont appelés "méthodes sûres", et ils renvoient une copie de l'original avec des modifications appliquées à la copie , avec l'appel inchangé. 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

Ce sorties:

A STRING
a string

Gardez à l'esprit, c'est juste une convention, mais beaucoup de classes Ruby suivre. Il vous aide également à garder suivi de ce qui est modifié dans votre code.

532
répondu tgamblin 2017-11-14 22:54:22

Le point d'exclamation signifie beaucoup de choses, et parfois vous ne pouvez pas dire beaucoup de choses autres que "c'est dangereux, faites attention".

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

d'Autres bibliothèques peuvent l'utiliser différemment. Dans les Rails, un point d'exclamation signifie souvent que la méthode va jeter une exception sur la défaillance plutôt que d'échouer silencieusement.

c'est une convention d'appellation mais beaucoup de gens l'utilisent de façon subtilement différente. Dans votre propre code une bonne règle de base est de l'utiliser chaque fois qu'une méthode fait quelque chose de "dangereux", en particulier lorsqu'il existe deux méthodes portant le même nom et que l'une d'elles est plus "dangereuse" que l'autre. "Dangereux" peut signifier presque tout.

125
répondu Brian Carper 2009-03-04 21:59:56

cette convention d'appellation est levée de Scheme .

1.3.5 conventions D'appellation

par convention, les noms des procédures que toujours retourner une valeur booléenne habituellement à la fin `?". De telles procédures sont appelés prédicats.

par convention, les noms des procédures qui stockent des valeurs dans emplacements attribués (voir Section 3.4)) habituellement à la fin `!". De telles procédures sont appelées procédures de mutation. Par convention, la valeur rendue par un la procédure de mutation n'est pas spécifiée.

60
répondu Steven Huwig 2009-03-04 21:44:52

! signifie généralement que la méthode agit sur l'objet au lieu de retourner un résultat. Du livre programmation Ruby :

méthodes qui sont "dangereux", ou modifier le récepteur, pourrait être nommé avec un arrière-plan "!".

23
répondu Pesto 2014-08-18 05:08:02

de themomorohoax.com:

Un bang peut être utilisé dans les manières, dans l'ordre de mes préférences personnelles.

1) une méthode d'enregistrement active soulève une erreur si la méthode ne fait pas ce qu'il dit il le fera.

2) une méthode d'enregistrement active sauve l'enregistrement ou une méthode sauve un l'objet (ex: bande!)

3) une méthode fait quelque chose de "supplémentaire", comme des postes à un endroit, ou fait un peu d'action.

le point est: Utilisez seulement un bang quand vous avez vraiment pensé à savoir si il est nécessaire, pour sauver d'autres développeurs, la gêne d'avoir à vérifier pourquoi vous utilisez un bang.

the bang fournit deux indices à d'autres développeurs.

1) qu'il n'est pas nécessaire de sauver l'objet après avoir appelé le méthode.

2) lorsque vous appelez la méthode, la db va être changé.

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

14
répondu Edward Castaño 2011-09-09 00:05:46

Il est plus exact de dire que les méthodes avec un Bang! sont les plus dangereux ou surprenant version. Il existe de nombreuses méthodes qui mutent sans Bangs tels que .destroy et en général les méthodes ont bangs seulement là où une alternative plus sûre existe dans le lib core.

par exemple, sur le tableau 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 de simplement retourner self.

la seule méthode non mutante que j'ai trouvée avec un bang est Kernel 's .exit! " ce qui est plus surprenant que .exit parce que vous ne pouvez pas attraper SystemExit alors que le processus est en train de se fermer.

rail et ActiveRecord poursuit cette tendance en utilisant bang pour des effets plus "surprenants" comme .create! qui soulève des erreurs en cas de défaillance.

14
répondu BookOfGreg 2017-05-23 11:55:11

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 changerait en downcase de façon permanente. downcase! ne retournerait pas un nouvel objet string mais remplacerait la chaîne en place, changeant totalement le foo en downcase. Je vous conseille de ne pas utiliser downcase! sauf si c'est absolument nécessaire.

6
répondu Mirage 2014-02-15 22:47:43

appelés "méthodes destructives" ils 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]
1
répondu Mittinti Ramana Murthy 2017-05-23 14:43:20

résultat: ! les méthodes changent simplement 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.

n'utilisez ! que si vous ne prévoyez pas d'avoir besoin de la valeur originale stockée à 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

ou

foo = "word"
puts foo.capitalize

au lieu de

foo = "word"
foo.capitalize!
puts foo

juste au cas où je voudrais accéder à nouveau à la valeur originale.

0
répondu Charles 2015-07-23 21:10:59
!

j'aime à penser à ceci comme un changement explosif qui détruit tout ce qui est allé avant lui. Bang ou point d'exclamation signifie que vous faites un changement enregistré permanent dans votre code.

Si vous utilisez par exemple Ruby méthode de substitution globale gsub! la substitution est permanente.

une autre façon de l'imaginer, c'est d'ouvrir un fichier texte et de faire find and replace, suivi d'une sauvegarde. ! fait la même chose dans votre code.

un autre rappel utile si vous venez du monde de bash est sed -i a cet effet similaire de faire le changement enregistré permanent.

0
répondu Charlie Wood 2017-04-03 15:16:07