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?
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#(0)
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.
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#(0)
That's not the question, though; the question is why #first doesn't
actually call #.
David
--
Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS June 9-12 Berlin
ADVANCING WITH RAILS June 16-19 Berlin
INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!
"David A. Black" <dblack@rubypal.com> 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#(0)
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#(0)
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
···
On Wed, Apr 30, 2008 at 4:50 AM, Brian Adkins <lojicdotcom@gmail.com> wrote:
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.
···
On Apr 29, 5:36 pm, Peña, Botp <b...@delmonte-phil.com> wrote:
from: Fredrik [mailto:fredj...@gmail.com]
# 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"
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.
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.
# From: Fredrik [mailto:fredjoha@gmail.com]
# # 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
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] ???
# 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?
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] ???
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
···
On Tue, 29 Apr 2008, Fredrik wrote:
--
Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS June 9-12 Berlin
ADVANCING WITH RAILS June 16-19 Berlin
INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!