On 30.12.2007 02:17, MonkeeSage wrote:
value is immutable.
you seem to be objecting based on semantics and I’m trying to understand
end
Which means that #last is a specialized form of #[], which means that
it is another level of abstraction removed from #[]. So the result of
#last is the same as #[-1], but the semantics of #last are more like
#length or #pop, which are also a level of abstraction removed from
#[].
I do not understand your talking of “removing a level of abstraction”.
Basically, I’d say #first and #last are more abstract than #[] because
they add semantics and they are (or at least could be) built on top of
#[]. You do not have to provide the detail of the index to access.
Then, comparing #[], #first and #last with #length and #pop seems very
strange to me - for different reasons: #length has nothing to do with
element access (which is all #[], #first and #last are about). #pop on
the other hand does deal with element access but it also modifies the
Array.
Once again, I’m not arguing against #last=, per se, but I fail to
see how it differs at the present time from, for example:
class Array
def foo
self[self.length-1]
end
end
Ah, I believe I start to see something: you do not seem to recognize #[]
and #[]= as regular methods. With the implementation of #foo that you
present above you can not do this assignment:
[1,2,3].foo = 25
Consider this:
irb(main):001:0> class Foo
irb(main):002:1> def last;1;end
irb(main):003:1> end
=> nil
irb(main):004:0> f=Foo.new
=> #Foo:0x7ff958ec
irb(main):005:0> f.last
=> 1
irb(main):006:0> f.last = 10
NoMethodError: undefined method `last=’ for #Foo:0x7ff958ec
from (irb):6
from :0
irb(main):007:0> class Foo
irb(main):008:1> def last=(x) puts “assigned”; end
irb(main):009:1> end
=> nil
irb(main):010:0> f.last = 10
assigned
=> 10
You have to implement #last= in order to be able to do the assignment.
You do not automatically get it for free when defining #last. So #last
corresponds to (or: “can be implemented in terms of”) #[] while #last=
corresponds to #[]=. Similarly #last also works with frozen instances
(like #[] does) but #last= does not (like #[]= does not). Does this
make sense?
I do not know your (programming) background but if you think Ruby’s
Array is similar to a C array then maybe you should drop that notion
because they are vastly different (note, this does not refer to the
implementation but to how they are used in each language).
Or more simply, [1,2,3].length = 20.
As #length has nothing to do with element access I would expect the
length of the Array to change when assigning to it (e.g. by pruning or
appending nils).
Of course, one could implement those methods where they so inclined,
but it would make the semantics of, e.g., #foo and #foo= very
different. In this case of #last / #first, I don’t think it is very
confusing to have those different semantics; I was probably being too
much of a stickler for “purism”.
Again, this semantic difference you are talking about is still not clear
to me. The semantic between #last and #last= and #first and #first= I
can see at the moment is the lack of a parameter as has been mentioned:
while you can make #last and #first return a sub array you can only
assign to a single element with the assignment variants. But that seems
ok to me.
Kind regards
robert