I made a class that is a subclass of Array :
class MyClass < Array
def
“Here you go: #{super(i)}”
end
end
and I thought that Array#first and Array#last was just syntactic sugar
that would translate to Array#[0] and Array#[-1] respectively. But
it’s not:
irb> g = MyClass.new([1,2,3])
=> [1, 2, 3]
irb> g[0]
=> “Here you go: 1”
irb> g.first
=> 1
Now, isn’t that really, really crazy? Am I supposed to define
MyClass#first and MyClass#last separately???
Best regards,
Fredrik
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Fredrik wrote:
| I made a class that is a subclass of Array :
|
| class MyClass < Array
| def
| “Here you go: #{super(i)}”
| end
| end
|
| and I thought that Array#first and Array#last was just syntactic sugar
| that would translate to Array#[0] and Array#[-1] respectively. But
| it’s not:
|
| irb> g = MyClass.new([1,2,3])
| => [1, 2, 3]
| irb> g[0]
| => “Here you go: 1”
| irb> g.first
| => 1
|
| Now, isn’t that really, really crazy? Am I supposed to define
| MyClass#first and MyClass#last separately???
C:\scripts>ruby temp.rb
Here you go: 1
1
C:\scripts>cat temp.rb
class MyClass < Array
~ def
~ “Here you go: #{super(i)}”
~ end
end
g = MyClass.new([1,2,3])
puts g[0]
puts g.first
C:\scripts>ruby -v
ruby 1.8.6 (2008-03-03 patchlevel 114) [i386-mswin32]
Hm…
Phillip G.
Twitter: twitter.com/cynicalryan
Blog: http://justarubyist.blogspot.com
~ Calvin: Can you make a living playing silly games? His Dad:
Actually, you can be among the most overpaid people on the planet.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iEYEARECAAYFAkgW1xUACgkQbtAgaoJTgL8ozACfeThkZk1S/FDCSSYeSBEhog6V
PA4AoIQJjVJlB092JSYBPAXA4jF7UYfE
=c2AX
-----END PGP SIGNATURE-----
I see that Array#each wont do what I want it to do either. I guess I
have to do it like this:
class MyClass < Array
def initialize(arg)
super(arg.map{ |i| “Here you go: #{i}”})
end
end
This would give me all the behavior I want, except that it’s a
wasteful use of memory if I have a really big array and want to
include the same text in all my array elements. I just want to have
some fixed text attached to ANY operations I do with array elements.
To achieve that, do I really need to do it like this?
/Fredrik
from: Fredrik [mailto:[email protected]]
include the same text in all my array elements. I just want to have
some fixed text attached to ANY operations I do with array elements.
there are other better ways, but i just extended your initial
thought/code,
class MyArray < Array
Array.methods.each do |m|
define_method(m) do
“Here you go: #{super}”
end
end
end
#=>…
g=MyArray.new [1,2,3]
#=> Here you go: [1, 2, 3]
g[1]
#=> “Here you go: 2”
g[0]
#=> “Here you go: 1”
g.first
#=> 1
g.last
#=> 3
g[-1]
#=> “Here you go: 3”
kind regards -botp
From: Peña, Botp [mailto:[email protected]]
#…
Array.methods.each do |m|
^^^^^^^^^^^^^
make that
Array.instance_methods.each do |m|
sorry, my bad.
so,
class MyArray < Array
Array.instance_methods.each do |m|
define_method(m) do
“Here you go: #{super}”
end
end
end
#=>…
g=MyArray.new [1,2,3]
#=> Here you go: [1, 2, 3]
g[0]
#=> “Here you go: 1”
g.first
#=> “Here you go: 1”
g[-1]
#=> “Here you go: 3”
g.last
#=> “Here you go: 3”
g[2]
#=> “Here you go: 3”
kind regards -botp
Maybe is better using instance_methods instead
class MyArray < Array
Array.instance_methods.each do |m|
define_method(m) do
“Here you go: #{super}”
end
end
end
irb(main):033:0> g=MyArray.new [1,2,3]
=> Here you go: [1, 2, 3]
irb(main):034:0> g.first
=> “Here you go: 1”
irb(main):035:0>
On Apr 29, 5:36 pm, Peña, Botp [email protected] wrote:
end
g.first
#=> 1
g.last
#=> 3
g[-1]
#=> “Here you go: 3”
kind regards -botp
But that doesn’t work (though I don’t understand why). I want it to
always say “Here you go: …”, no matter how I retrieve an element out
of the array.
From: Fredrik [mailto:[email protected]]
irb> g.size
=> “Here you go: 3”
That’s a strange size
So this solution solves some problems but creates new ones instead…
you wanted to put text on all ops
so even
irb> g.last
=> “Here you go: 3”
is already strange, right?
my suggestion is if you just want to view some output w text, just
wrapped it in a text,
like so,
puts “Here you go: #{g.last}”
kind regards -botp
Thanks! But how about this then:
irb> g.size
=> “Here you go: 3”
That’s a strange size 
So this solution solves some problems but creates new ones instead…
I’m sorry, I think I am too vague about what I want to achieve. What I
want is to have is an “array” that behaves exactly like an array
EXCEPT that each element has some text attached to it. Array#size is
not an element but Array#last is an element for example.
Maybe it’s not doable in any other way than copying the text into each
element since I would like this text to follow into Array#each,
Array#map and all those methods.
What I am still thinking about though, is this:
Why on earth is Array#first not calling Array#[0] ???
Fredrik
From: Fredrik [mailto:[email protected]]
I’m sorry, I think I am too vague about what I want to achieve. What I
want is to have is an “array” that behaves exactly like an array
EXCEPT that each element has some text attached to it. Array#size is
not an element but Array#last is an element for example.
Maybe it’s not doable in any other way than copying the text into each
element since I would like this text to follow into Array#each,
Array#map and all those methods.
ok, then just modify those you want
eg,
class Array2 < Array
%w([] first last).each do |m|
define_method(m) do
r = super
puts “Here you go: #{r}”
r
end
end
end
#=> [“[]”, “first”, “last”]
a=Array2.new [1,2,3]
#=> [1, 2, 3]
a[0]
Here you go: 1
#=> 1
a.first
Here you go: 1
#=> 1
a.size
#=> 3
What I am still thinking about though, is this:
Why on earth is Array#first not calling Array#[0] ???
that would be calling two methods, and would be quite expensive, right?
kind regards -botp
From: Peña, Botp [mailto:[email protected]]
# irb> g.size
# => “Here you go: 3”
# That’s a strange size
# So this solution solves some problems but creates new ones
instead…
you wanted to put text on all ops
so even
irb> g.last
=> “Here you go: 3”
is already strange, right?
my suggestion is if you just want to view some output w text,
just wrapped it in a text,
like so,
puts “Here you go: #{g.last}”
ok, how about combining what we want, ie, put the text yet still
returning the object, so
class MyArray < Array
Array.instance_methods.each do |m|
define_method(m) do
r=super
puts “Here you go: #{r}”
r
end
end
end
#=> …
g=MyArray.new [1,2,3]
Here you go: [1, 2, 3]
#=> [1, 2, 3]
g[0]
Here you go: 1
#=> 1
g.first
Here you go: 1
#=> 1
g.last
Here you go: 3
#=> 3
g.size
Here you go: 3
#=> 3
puts “size is: #{g.size}”
Here you go: 3
size is: 3
#=> nil
is that ok?
kind regards -botp
“David A. Black” [email protected] writes:
On Tue, 29 Apr 2008, Fredrik wrote:
What I am still thinking about though, is this:
Why on earth is Array#first not calling Array#[0] ???
The real question is: why should it? They’re completely separate
methods.
I can’t think of a good reason to ever have: Array#first != Array#
Hi –
On Tue, 29 Apr 2008, Fredrik wrote:
Why on earth is Array#first not calling Array#[0] ???
The real question is: why should it? They’re completely separate
methods.
Mind you, if you dig through the ruby-lang archives, you’ll find Ben
Tilly and Mathieu Bouchard patiently explaining to me the answer to
the same question
My initial assumption was that all get and set
operations would go through [] and []=. They don’t, though. It would
make it very easy to do Perl-style “tie” operations if they did, but
it would also be less efficient; in other words, not going through []
and []= is an optimization.
I’m perennially working on a “tie” module, and never seem to get it
how I want it… but I’ll have another look at it and see how close
it’s getting.
David
Hi –
On Wed, 30 Apr 2008, Brian A. wrote:
“David A. Black” [email protected] writes:
On Tue, 29 Apr 2008, Fredrik wrote:
What I am still thinking about though, is this:
Why on earth is Array#first not calling Array#[0] ???
The real question is: why should it? They’re completely separate
methods.
I can’t think of a good reason to ever have: Array#first != Array#
That’s not the question, though; the question is why #first doesn’t
actually call #[].
David
Brian A. [email protected] writes:
“David A. Black” [email protected] writes:
On Tue, 29 Apr 2008, Fredrik wrote:
What I am still thinking about though, is this:
Why on earth is Array#first not calling Array#[0] ???
The real question is: why should it? They’re completely separate
methods.
I can’t think of a good reason to ever have: Array#first != Array#
Sorry about that. I’m having a bit of trouble with the Gnus news reader,
so this got attached to the wrong message - it should’ve followed
David’s of course.
Ok, I got it. So Array#first is a matter of optimization. I thought it
was syntactic sugar that the Ruby interpreter translates to Array#[]
(0).
But I understand now that Array#first is not there for my coding
convenience but rather for computational speed.
Thanks for clearing it up!
Fredrik
Hi,
On Wed, Apr 30, 2008 at 4:50 AM, Brian A. [email protected]
wrote:
“David A. Black” [email protected] writes:
The real question is: why should it? They’re completely separate
methods.
I can’t think of a good reason to ever have: Array#first != Array#
They’re still separate methods. The point is, internally, Ruby saves
another
dynamic method dispatch by hard-coding Array#first to just grab the
first
item from the internal data structure – just like calling Array#
would, but it’s faster. It might even make a noticeable difference in
some
application that calls Array#first and #last a lot… (I don’t propose
such
cases do exist, but every small part counts)
array.c:
static VALUE
rb_ary_first(int argc, VALUE *argv, VALUE ary)
{
if (argc == 0) {
if (RARRAY_LEN(ary) == 0) return Qnil;
return RARRAY_PTR(ary)[0];
}
else {
return ary_shared_first(argc, argv, ary, Qfalse);
}
}
Here seen retrieving the first item manually.
Arlen
Fredrik wrote;
But I understand now that Array#first is not there for my coding
convenience but rather for computational speed.
I’m using some other scripting language (PHP), and when it becomes known
that method A to do something is faster than method B to do something,
everybody turns to use method A no matter how ugly it looks. (When I say
“method” I don’t mean the object orient meaning. I simply mean “way”.)
Now,
If #first was slower than #[0], nobody would have used it!
Having #first is nice. It has merit (clarity). So the only way to have
it and have people use it is not to have it slower than #[0].
So on the contrary: #first is there for your convenient, not for
computational speed.