safe array index ?

C

Christer Nilsson

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 [](index)
raise "index error" if index.abs >= self.size
self.old(index)
end
end

Is there something like Array.indexcheck = true ?

Christer
 
E

Edward Faulkner

--SLDf9lqlvOQaIe6s
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

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 [](index)
raise "index error" if index.abs >= size
super(index)
end
end

regards,
Ed

--SLDf9lqlvOQaIe6s
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: Digital signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFDxUYYnhUz11p9MSARAr7YAJ4pOiznxR05O3MRKBdAgM1+y+iUkACeJ9kf
adda4c+s+1uOh6qHI9krorM=
=Vppw
-----END PGP SIGNATURE-----

--SLDf9lqlvOQaIe6s--
 
F

Florian Frank

Christer said:
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.
a.fetch 99 # => raises IndexError: index 99 out of array
 
C

Christer Nilsson

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 [](index)
fetch index
end
end

Christer
 
P

Phrogz

Christer said:
class SafeArray < DelegateClass(Array)
def [](index)
fetch index
end
end

Or, even easier:

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

David Vallner

Phrogz said:
Christer Nilsson wrote:

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

Or, even easier:

class SafeArray < DelegateClass(Array)
alias_method :[], :fetch
end
Groan at the different argument order of the alias statement and
#alias_method.
 
C

Christer Nilsson

Christian said:
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.
 
R

Robert Klemme

David said:
Phrogz said:
Christer Nilsson wrote:

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

Or, even easier:

class SafeArray < DelegateClass(Array)
alias_method :[], :fetch
end
Groan at the different argument order of the alias statement and
#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
 
D

David Vallner

David said:
Phrogz said:
Christer Nilsson wrote:


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



Or, even easier:

class SafeArray < DelegateClass(Array)
alias_method :[], :fetch
end
Groan at the different argument order of the alias statement and
#alias_method.
class Foo
def bar() "bar" end
alias :b :bar
end =3D> nil
Foo.new.b =3D> "bar"
class Bar
def foo() "foo" end
alias_method :f, :foo
end =3D> Bar
Bar.new.f
=3D> "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


My bad. However, it seems alias_method silently lets me use an undefined =
=20
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 class `Foo'
from (irb):5
irb(main):008:0> Foo.new.bar
BAR
=3D> 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 method `bar2' for #<Foo:0x102934f0>
from (irb):10

David Vallner
 
P

Pit Capitain

David said:
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 class `Foo'
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
 
W

Wilson Bilkovich

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 [](index)
raise "index error" if index.abs >=3D 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 [](index)
irb(main):003:2> raise "Index error" if index.abs >=3D size
irb(main):004:2> super(index)
irb(main):005:2> end
irb(main):006:1> end
=3D> nil
irb(main):007:0> a =3D SafeArray.new
=3D> []
irb(main):008:0> a.concat [1,2,3,4,5]
=3D> [1, 2, 3, 4, 5]
irb(main):009:0> b =3D Array.new
=3D> []
irb(main):010:0> b.concat [1,2,3,4,5]
=3D> [1, 2, 3, 4, 5]
irb(main):011:0> a
=3D> [1, 2, 3, 4, 5]
irb(main):012:0> b
=3D> [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]
=3D> nil
 
J

James Edward Gray II

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 Gray II
 
D

David Vallner

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

Regards,
Pit


<dense>
D'oh... Ah well, I'm deformed by JSP compilers slapping me left right and=
=20
center at office it seems.
</dense>

Cheers.

David Vallner
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,996
Messages
2,570,238
Members
46,826
Latest member
robinsontor

Latest Threads

Top