Safe array index?


#1

Is it possible to catch index out of range ?

a = [1,2]

a[99] returns nil, I would like to get an error.

I’ve tried to define a SafeArray class, but failed.

I managed to redefine Array, but I want to have both possibilities.

class Array
alias old []
def
raise “index error” if index.abs >= self.size
self.old(index)
end
end

Is there something like Array.indexcheck = true ?

Christer


#2

On Thu, Jan 12, 2006 at 02:40:40AM +0900, Christer N. wrote:

Is it possible to catch index out of range ?
I managed to redefine Array, but I want to have both possibilities.

You can use a delegator:

require ‘delegate’

class SafeArray < DelegateClass(Array)
def
raise “index error” if index.abs >= size
super(index)
end
end

regards,
Ed


#3

Christer N. wrote:

a.fetch 99 # => raises IndexError: index 99 out of array


#4

Ed and Florian, thank you both!

fetch() has the requested behaviour, but [] is nicer, syntactically.

a.fetch(2).fetch(3) # safe
a[2][3] # nice

with delegate I can have both!

class SafeArray < DelegateClass(Array)
def
fetch index
end
end

Christer


#5

Christer N. wrote:

class SafeArray < DelegateClass(Array)
def
fetch index
end
end

Or, even easier:

class SafeArray < DelegateClass(Array)
alias_method :[], :fetch
end


#6

Phrogz wrote:

Or, even easier:

class SafeArray < DelegateClass(Array)
alias_method :[], :fetch
end

Groan at the different argument order of the alias statement and
#alias_method.


#7

Edward F. removed_email_address@domain.invalid writes:

raise "index error" if index.abs >= size
super(index)

end
end

Why do you use a delegator and don’t just directly inherit from Array?


#8

Christian N. wrote:

Why do you use a delegator and don’t just directly inherit from Array?

I tried your suggestion, and it seems to work perfect as well.
Can’t get simpler than this, I guess:

class SafeArray < Array
alias_method :[], :fetch
end

My original inheritance used @arr=Array.new and that was a dead end.


#9

David V. wrote:

#alias_method.

class Foo
def bar() “bar” end
alias :b :bar
end
=> nil

Foo.new.b
=> “bar”

class Bar
def foo() “foo” end
alias_method :f, :foo
end
=> Bar

Bar.new.f
=> “foo”

It seems to me order is the same: first the new name then the old name.
Am I missing something here?

Kind regards

robert

#10

On Thu, 12 Jan 2006 12:08:05 +0100, Robert K. removed_email_address@domain.invalid
wrote:

end
Groan at the different argument order of the alias statement and
def foo() “foo” end

robert

My bad. However, it seems alias_method silently lets me use an undefined
method name as the old name, which got me confused:

irb(main):001:0> class Foo
irb(main):002:1> def bar
irb(main):003:2> puts “BAR”
irb(main):004:2> end
irb(main):005:1> alias :bar :bar1
irb(main):006:1> alias_method :bar, :bar2
irb(main):007:1> end
NameError: undefined method bar1' for classFoo’
from (irb):5
irb(main):008:0> Foo.new.bar
BAR
=> nil
irb(main):009:0> Foo.new.bar1
NoMethodError: undefined method bar1' for #<Foo:0x10295848> from (irb):9 irb(main):010:0> Foo.new.bar2 NoMethodError: undefined methodbar2’ for #Foo:0x102934f0
from (irb):10

David V.


#11

On 1/11/06, Edward F. removed_email_address@domain.invalid wrote:

raise "index error" if index.abs >= size
super(index)

end
end

I’ve been trying to get my head around Delegator, but I’m not seeing
what it does here.
Subclassing Array seems to work the same way.

irb session:
irb(main):001:0> class SafeArray < Array
irb(main):002:1> def
irb(main):003:2> raise “Index error” if index.abs >= size
irb(main):004:2> super(index)
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> a = SafeArray.new
=> []
irb(main):008:0> a.concat [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
irb(main):009:0> b = Array.new
=> []
irb(main):010:0> b.concat [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
irb(main):011:0> a
=> [1, 2, 3, 4, 5]
irb(main):012:0> b
=> [1, 2, 3, 4, 5]
irb(main):013:0> a[9]
RuntimeError: Index error
from (irb):3:in `[]’
from (irb):13
irb(main):014:0> b[9]
=> nil


#12

David V. schrieb:

NameError: undefined method bar1' for classFoo’
from (irb):5

After the error on line 5, line 6 isn’t executed anymore. Switch lines 5
and 6 and you see what I mean.

Regards,
Pit


#13

On Thu, 12 Jan 2006 15:10:18 +0100, Pit C. removed_email_address@domain.invalid
wrote:

NameError: undefined method bar1' for classFoo’
from (irb):5

After the error on line 5, line 6 isn’t executed anymore. Switch lines 5
and 6 and you see what I mean.

Regards,
Pit

D'oh... Ah well, I'm deformed by JSP compilers slapping me left right and center at office it seems.

Cheers.

David V.


#14

On Jan 12, 2006, at 8:51 AM, Wilson B. wrote:

I’ve been trying to get my head around Delegator, but I’m not seeing
what it does here.

One problem is that all the examples in this thread have been leaving
out the critical step, setting the object to delegate too in the
constructor.

Delegator is for passing calls on to an object. See the sample
initialize() methods and documentation of DelegateClass() here:

http://www.ruby-doc.org/stdlib/libdoc/delegate/rdoc/index.html

Hope that helps.

James Edward G. II