Articles

How to Write a Case Expression in Ruby

Posted on

Stel je voor dat je een manier nodig hebt om de waarde van een object te controleren, en op basis daarvan een andere actie uit te voeren. De Object Georiënteerd Programmeren manier is om polymorfisme te gebruiken, en we zullen zien hoe je dat in een seconde kunt doen.

Maar laten we eerst eens kijken hoe de case expressie werkt, en hoe je het kunt gebruiken om het hierboven genoemde doel te bereiken.

Hoe werkt de case?

Er zijn twee hoofdonderdelen aan de case expressie. De case-clausule, en de when-clausule.

De when clausule is de expressie die de ontvanger van de operator definieert (standaard ===), en de case clausule definieert het argument dat aan de operator wordt doorgegeven.

Laten we eens een voorbeeld bekijken.

case awhen String #..end

Dus je kunt aan bovenstaand voorbeeld denken als String === a, of String.===(a).

Ten slotte is er ook nog een else-clausule die je kunt gebruiken voor als er geen overeenkomst is.

case my_objectwhen String "This is a string"else "I have no idea what this is"end

De drievoudige gelijk-operator (===)

Bestandaard gebruikt case de drievoudige gelijk-operator (===) om de vergelijking uit te voeren.

Het probleem met === is dat het niets met gelijkheid te maken heeft. Het is standaard aliased naar de dubbele gelijkheid operator (==) die normaal controleert of twee objecten een gelijke waarde hebben, maar het kan worden gedefinieerd om van alles te betekenen.

Bijv. een range definieert het als een alias voor includes?, een regex definieert het als een alias voor match, een class voor is_a?, een proc voor call. Je snapt het idee.

Die operator werkt zoals verwacht met literals, maar niet met classes:

1 === 1 # => trueNumeric === Numeric # => false

Dat komt omdat de === een alias is voor kind_of?. En hier zijn de docs voor kind_of?.

kind_van?(class) → true of false

Returns true als class de class van obj is, of als class een van de superklasses van obj is of modules die in obj zijn opgenomen.

Dit betekent dat als je een case ... when over de klasse van een object wilt doen, dit niet zal werken:

obj = 'Hi'case obj.classwhen String "It's a string"end

Dat is omdat, het vertaalt naar String === String. En dat levert false op.

De standaard operator

De case expressie heeft een standaard operator. En dat betekent dat je hem niet hoeft te specificeren. Dat is heel mooi, want je kunt gewoon when String schrijven en het gaat standaard naar de === operator.

Maar, er zijn momenten dat je een andere operator wilt gebruiken. En Ruby staat je toe om dat te doen. Hier lees je hoe.

casewhen a < 3 "Smaller than 3"end

Case is een expressie

Net zoals de naam al zegt, is het hele ding een expressie. Dat betekent dat het naar een waarde wordt geëvalueerd. Dus je kunt het resultaat van de hele case expressie aan een variabele toewijzen, zoals dit.

value = case when a < 3 "Smaller than 3" end

Er is geen fall-through

Als je uit andere talen komt, heb je waarschijnlijk wel eens een switch statement of iets dergelijks gebruikt, en hebt u gemerkt dat case geen trefwoorden gebruikt zoals break om de stroom te onderbreken.

Dat komt omdat er geen fall-through is met case. Het retourneert alleen de waarde van de expressie waarop is gematcht en dat is het.

Meerdere matches

Tot nu toe hebt u slechts één waarde gebruikt voor de when-clausule. Maar u kunt meerdere waarden gebruiken.

case awhen 1..3 "Small number"end

Het matchen van regexes

U kunt case expressies gebruiken om met alles te matchen. Maar voor het geval het niet duidelijk is, je kunt ook regexen, of lambdas gebruiken. Hier is een voorbeeld.

even = ->(x) { x % 2 == 0 }case awhen even "It's even"when /^+$/ "It's an integer"end

Definieer je eigen

Een van de minder bekende feiten is dat je je eigen comparators kunt definiëren.

Text = Struct.new(:min_length) do def ===(string) string.size > min_length && string.is_a?(String) endendcase awhen Text.new(100) "It's text"end

In het bovenstaande voorbeeld, als a een tekenreeks is van meer dan 100 tekens, dan zal de case expressie It's text teruggeven.

Gebruik in plaats daarvan polymorfisme

Ik ga hier niet in op de voordelen van OOP, daar kun je meer over lezen in het Object-georiënteerd programmeren met Ruby artikel, maar ik ga je laten zien hoe je polymorfisme kunt gebruiken om een case expressie te vervangen.

De case versie

class Person attr_reader :country def initialize(country) @country = country end def nationality case country when "USA" "This guy is an American" when "Romania" "This guy is a Romanian" end endendjohn = Person.new("USA")puts john.nationality # => This guy is an American

De OOP versie

class Person attr_reader :country def initialize(country) @country = country end def nationality country.nationality endendclass America def nationality "This guy is an American" endendclass Romania def nationality "This guy is a Romanian" endendjohn = Person.new(America.new)puts john.nationality # => This guy is an American

Het is een goed idee om zo veel mogelijk flow control code te verwijderen (i.d.w.z. ifs, en case expressies) zoveel mogelijk te verwijderen. Het verbetert het naleven van het Single Responsibility Principle en maakt het programma leesbaarder in het algemeen.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *