4
votes

Comment faire une déclaration de casse ruby ​​utiliser égal à (==) plutôt que trois quals (===)

La déclaration de cas de Ruby utilise === par défaut. Y a-t-il un moyen de le faire utiliser 'égal à' (c'est-à-dire == ) à la place?

La motivation pour le faire est que j'ai 5 instructions if qui très joliment remplacé par un commutateur, mais j'ai été un peu surpris d'apprendre que

case datatype
when String
puts "This will NOT print"
end
if datatype == String
puts "This will print"
end

n'est pas la même chose que

XXX


3 commentaires

ref pouvez-vous nous aider.


La déclaration de cas de Ruby utilise === . Il ne "l'utilise pas par défaut ".


Je suis tombé sur ceci (on dirait que le comportement de cas par rapport aux classes en a déclenché d'autres aussi


4 Réponses :


4
votes

Vous ne pouvez pas laisser cas ne pas utiliser === , mais vous pouvez redéfinir === pour utiliser == .

class MetaClass
  def initialize klass
    @klass = klass
  end

  def ===instance
    instance == @klass
  end
end

def meta klass
  MetaClass.new(klass)
end

case datatype
when meta(String)
  puts "This will print"
end
# >> This will print

Vous pouvez également créer une classe spécifique pour cela.

class Class
  alias === ==
end

case datatype
when String
  puts "This will print"
end
# >> This will print


3 commentaires

Est-il dangereux de redéfinir === ? Pourrait-il être utilisé dans d'autres méthodes (dont je ne suis peut-être pas au courant) et est-il possible que je ruine les autres méthodes en le redéfinissant?


=== est rarement utilisé autrement que dans les instructions case , donc ce n'est pas si dangereux. Mais si vous avez des soucis avec l'interaction avec d'autres parties du code, envisagez de changer l'alias en une définition de méthode dans un raffinement et utilisez l'instruction case appropriée dans le cadre du raffinement.


C'est un peu la même chose ici mais joliment mis ici +1



3
votes

Ce serait une approche plus concise et plus claire (IMSO) de ce que @sawa avait suggéré. Utilisez Î »au lieu de la classe wrapper.

META = ->(type, receiver) { receiver == type }

case "string".class
when META.curry[Integer] then puts 'integer'  
when META.curry[String] then puts 'string'  
end  

#⇒ "string"

Cette solution utilise Proc # curry et Proc # === sous le capot.


0 commentaires

2
votes

Similaire à la réponse d'Aleksei Matiushkin, mais sans le curry:

datatype = "string"
case datatype
when String
puts "This will print"
end

Que se passe-t-il ici?

  • La première ligne définit un proc qui renvoie un autre proc
  • proc [x] est identique à proc.call(x)
  • proc. === (x) est identique à proc.call(x)
  • is_class [Integer] renvoie un proc qui fait {| val | val == Integer}
  • ..qui est appelé par cas avec le paramètre de cas comme argument à cause de === ==> call .

Le gros inconvénient est que cela crée beaucoup de procs et semble bizarre.

Bien sûr, la solution évidente à votre question serait de ne pas faire datatype = "string". classe :

is_class = ->(klass) { ->(item) { item == klass } }

10.times do
  case ['abc', 123].sample.class
  when is_class[String]
    puts "it's the abc"
  when is_class[Integer]
    puts "easy as 123"
  end
end


0 commentaires

1
votes

Vous pouvez également utiliser la forme explicite de l'instruction case

datatype = test_object.class

case
when datatype == String
  puts "It's a string"
when datatype < Numeric
  puts "It's a number"
end

Notez que l'expression datatype sera vraie pour tous les types numériques.


0 commentaires