Range
s sono oggetti matematici che precedono di molto la programmazione e gli array. Quello che puoi fare con un Range
è controllare se un valore si trova entro un Range
.
L'iterazione su un Range
è non il caso d'uso principale; infatti, per un sacco di Range
s, non è nemmeno possibile. Per esempio. per un Range
di numeri reali, non puoi iterare su di esso perché non esiste il "prossimo numero reale": qualunque sia il numero reale che scegli come "il prossimo", ci sono ancora infiniti numeri reali tra la corrente e il "prossimo".
In Ruby, il protocollo Range
è diviso in due: verifica e iterazione dei membri. Gli oggetti utilizzati come endpoint in Range
s DEVONO implementare la porzione di controllo dei membri del protocollo e MAGGIO implementare ulteriormente la parte di iterazione del protocollo.
La parte di appartenenza del protocollo è semplice: sia l'oggetto di inizio che di fine devono rispondere al messaggio <=>
(il metodo di confronto combinato standard che restituisce -1
, 0
, 1
o nil
per oggetti che sono inferiori, uguali, maggiori o incomparabili). Per la parte di iterazione, anche l'oggetto start deve rispondere al messaggio succ
(e l'oggetto restituito deve rispondere a succ
e così via ...).
È perfettamente possibile in Ruby, ad esempio, costruire i seguenti Range
di Rational
numeri:
r = 1r..10r
Posso verificare l'appartenenza:
r.cover?(5r) #=> true
Ma non iterare:
r.to_a
# TypeError: can't iterate from Rational