From: Robert Klemme Date: 2008-01-01T00:05:00+09:00 Subject: Re: Add Array#first= and Array#last= to std lib On 31.12.2007 08:22, MonkeeSage wrote: > On Dec 30, 5:50 am, Robert Klemme wrote: >> On 30.12.2007 02:17, MonkeeSage wrote: >> >> >> >>> On Dec 29, 6:06 pm, Gary Wright wrote: >>>> On Dec 29, 2007, at 6:24 PM, MonkeeSage wrote: >>>>> I wasn't arguing for or against #last=, per se; I was only trying to >>>>> explain why it doesn't make sense, _to me_, "Unless the semantics [of >>>>> #last] change," to have #last=. I.e., #[] subscripts the array and >>>>> returns the value of the index, but #last returns the value of >>>>> subscripting the array at index #length-1; it is another level of >>>>> abstraction removed from #[]; so with those semantics, #last= would be >>>>> like #length= (or #pop=), and you end up with exceptions when the >>>>> value is immutable. >>>> Why do you shift your terminology when talking about last? Using >>>> your terminology but my mental model of arrays: >>>> #[n] subscripts the array with n and returns the value of the index >>>> #[-1] subscripts the array with (length-1) and returns the value of >>>> the index >>>> #last subscripts the array with (length-1) and returns the value of >>>> the index >>>> Why do you rephrase that last case as: >>>> #last returns the value of subscripting the array at index #length-1 >>>> Are you suggesting that #last does something distinctly different than >>>> subscripting via -1? If not then it would seem your argument against >>>> last= >>>> would apply just as well to 'array[-1] = x'. Are you suggesting that >>>> element assignment with negative subscripts also don't make sense to >>>> you? >>>> Objections to last= and first= based on redundancy is one thing, but >>>> you seem to be objecting based on semantics and I'm trying to understand >>>> that objection because the semantics seem to be quite natural to me. >>>> Gary Wright >>> As I understand it, #last is semantically equivalent to this code: >>> class Array >>> def last >>> self[self.length-1] >>> end >>> 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 >> => # >> irb(main):005:0> f.last >> => 1 >> irb(main):006:0> f.last = 10 >> NoMethodError: undefined method `last=' for # >> 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. > > I guess I still wasn't being clear (hey, I'm trying!). I understand > that you don't get a setter, #foo=, just by defining #foo; and I > realize that #[] and #[]= are methods like any other method. I surmise > that further attempts to explain my reasoning will only serve to > further muddy the water, so I'll withdraw my statements. Oh no, please don't do that! Now I will be wandering about for the rest of the year like a bewitched ghost and wondering what it was that you tried to convey... ;-) > I have no > real problem with #last= / #first=. I was more talking about > theoretical "purity" than practical application. But I think that with > ruby pragmatism is the rule; just ignore my previous comments. :) That'll be harder than it looks like. :-) Well, maybe with a new year at hand you might change your mind and take a fresh start at this. At least I for one would be interested in learning what it was that you were aiming at. Kind regards robert