Reputation: 231
Can anyone explain to me this method? If I send an index as 4,
what does the code
return actually?.
def getOffset(index)
@baseIndex = 0 if @baseIndex.nil?
raise IndexError if not \
(@baseIndex ... @baseIndex + length) === index
return index - @baseIndex
end
I am not able to understand the part after the first line.
Upvotes: 0
Views: 101
Reputation: 10997
# this sets the base index to 0 unless `@baseIndex` is defined
@baseIndex = 0 if @baseIndex.nil?
# this raises an error if the index you passed in is larger than the size of your array
raise IndexError if not (@baseIndex ... @baseIndex + length) === index
# this returns the offset
return index - @baseIndex
So, if you did not set @baseIndex
and passed 4
, this method would return 4
.
If you set @baseIndex
to 2
, this method would return 2
.
If you set @baseIndex
to 5
, this method would return an IndexError
.
Upvotes: 1
Reputation: 8821
===
is used to test equality within a when
clause of a case
statement.
For example:
(1...10) === 5 returns true.
(1...10) === 11 returns false.
Upvotes: 1
Reputation: 29318
You could also refactor the code a bit for readability such as
def get_offset_refactor(index)
@base_index ||= 0
(@base_index...@base_index + length).include?(index) ? index - @base_index : raise IndexError
end
This reads as
#if base index is not nil use it's value otherwise use 0
@base_index = @base_index || 0
#create a range from @base_index up to be not including @base_index + length
#check if index is included in that range
#if so then return index - @base_index
#otherwise raise an IndexError
(@base_index ... @base_index + length).include?(index) ? index - @base_index : raise IndexError
Example
#because this is not defined anywhere
def length
5
end
get_offset_refactor(4)
@base_index = @base_index || 0 #@base_index will now = 0 because it was not set
#next line becomes
(0...(0+5)).include?(4) ? 4 - 0 : raise(IndexError)
#^[0,1,2,3,4] ^does this include 4 => yes
#return 4 - 0
#=> 4
If you run it with a 5 then it will raise because [1,2,3,4]
does not include 5
.
Hope this helps you understand this method is highly reliant on one instance variable @base_index
and 1 method/local variable length
.
Upvotes: 1
Reputation: 114158
Your method's second line looks pretty confusing, let's refactor it:
raise IndexError if not \
(@baseIndex ... @baseIndex + length) === index
The above is actually a single line:
raise IndexError if not (@baseIndex ... @baseIndex + length) === index
The case equality operator Range#===
should not be called explicitly. Use include?
instead, which does the same:
raise IndexError if not (@baseIndex ... @baseIndex + length).include?(index)
Finally, if not
can be written as unless
and some spaces can be removed:
raise IndexError unless (@baseIndex...@baseIndex + length).include?(index)
Better.
Let's assume @baseIndex = 4
and length = 10
:
raise IndexError unless (@baseIndex...@baseIndex + length).include?(index)
# is evaluated as:
raise IndexError unless (4...4 + 10).include?(index)
# is evaluated as:
raise IndexError unless (4...14).include?(index)
It raises an IndexError
unless index
is between 4
and 14
(excluding 14). Otherwise, it continues with the next line and returns index - @baseIndex
.
snake_case
for method names and variables (@base_index
)return
unless necessaryget
and set
prefixes, i.e. def offset
is usually enoughinitialize @base_index
in your initializer
(not in your offset
method):
def initialize
@base_index = 0
end
extract the range calculation:
def valid_range
@base_index...@base_index + length
end
def offset(index)
raise IndexError unless valid_range.include?(index)
index - @base_index
end
Upvotes: 5