Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Add Array#first= and Array#last= to std lib

Reply
Thread Tools

Add Array#first= and Array#last= to std lib

 
 
MonkeeSage
Guest
Posts: n/a
 
      12-30-2007
On Dec 29, 6:06 pm, Gary Wright <(E-Mail Removed)> 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
#[]. 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

[1,2,3].foo = 25

Or more simply, [1,2,3].length = 20.

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".

Regards,
Jordan
 
Reply With Quote
 
 
 
 
Robert Klemme
Guest
Posts: n/a
 
      12-30-2007
On 30.12.2007 02:17, MonkeeSage wrote:
> On Dec 29, 6:06 pm, Gary Wright <(E-Mail Removed)> 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
=> #<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
 
Reply With Quote
 
 
 
 
Marc Heiler
Guest
Posts: n/a
 
      12-30-2007
> [1,2,3].length = 20

ewww. what is this
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
George
Guest
Posts: n/a
 
      12-30-2007
On Dec 30, 2007 10:55 PM, Robert Klemme <(E-Mail Removed)> wrote:
> 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 think I'm sold on the idea. I don't see the extra semantics of
#first and #last over the standard attribute behavior as a problem
either; the getters are just overloaded with a second meaning.

The only slight weirdness I see in it is that [].first = 1 would raise
an IndexError, which seems odd since it doesn't look like there's any
indexing going on. But I'm not sure what would make more sense, and
it's probably best to keep consistent with #[] anyway.

Regards,
George.

 
Reply With Quote
 
MonkeeSage
Guest
Posts: n/a
 
      12-31-2007
On Dec 30, 5:50 am, Robert Klemme <(E-Mail Removed)> wrote:
> On 30.12.2007 02:17, MonkeeSage wrote:
>
>
>
> > On Dec 29, 6:06 pm, Gary Wright <(E-Mail Removed)> 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
> => #<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


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. 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.

Regards,
Jordan
 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      12-31-2007
On 31.12.2007 08:22, MonkeeSage wrote:
> On Dec 30, 5:50 am, Robert Klemme <(E-Mail Removed)> wrote:
>> On 30.12.2007 02:17, MonkeeSage wrote:
>>
>>
>>
>>> On Dec 29, 6:06 pm, Gary Wright <(E-Mail Removed)> 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
>> => #<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.

>
> 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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
/usr/bin/ld: ../../dist/lib/libjsdombase_s.a(BlockGrouper.o)(.text+0x98): unresolvable relocation against symbol `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostre silverburgh.meryl@gmail.com C++ 3 03-09-2006 12:14 AM
error: 'std::ios_base& std::ios_base::operator=(const std::ios_base&)' is private Geoffrey S. Knauth C++ 6 01-18-2006 11:48 AM
xServices::CServices<TImp>::StHoldClientList::StHoldClientList(std::set<TImp*, std::less<TImp*>, std::allocator<TImp*> >&)': Vinu C++ 4 07-07-2005 06:08 AM
xServices::CServices<TImp>::StHoldClientList::StHoldClientList(std::set<TImp*, std::less<TImp*>, std::allocator<TImp*> >&)': Vinu C++ 0 07-06-2005 12:45 PM
std::map<int,std::set<std::string> > Wrong? (Segmentation fault.) Peter Jansson C++ 5 03-17-2005 06:34 AM



Advertisments