Add Array#first= and Array#last= to standard lib (#18)

Submitted by: Robert Klemme

This revision by: Robert Klemme

Date: Tue Jan 01 11:23:33 -0500 2008

View earlier revisions

ABSTRACT

Add Array#first and Array#last to the standard library for setting of first and last element. Behavior should be similar to assigning to [0] and [-1] but not throw an exception for empty Arrays. In this case the value is simply added.

PROBLEM

There is Array#first and #last for read only access. It would be nice to also have assignment to these special elements.

PROPOSAL

Add #first= and #last= to Array to allow for assignment of the first and last element. If the Array is empty, the element should simply be added.

ANALYSIS

No existing code will break.

Readability can be increased. Also code can be cleaner because no additional error checking is needed for assigning to the last element of an empty Array.

There is just a slight asymmetry because #first and #last allow retrieving a sub array (leading or trailing portion) when used with a numeric parameter. However, I believe that the added readability outweighs the drawback of asymmetry.

For more detailed analysis see http://blade.nagaokaut.ac.jp/cgi-bin/vframe.rb/ruby/ruby-talk/284960?284904-285503

IMPLEMENTATION

class Array def first=(v) self[ 0 ] = v end end

def last=(v)
  (self[ -1 ] = v) rescue self << v
end

Comments

from Gavin Kistner, Tue Jan 01 15:13:12 -0500 2008

On Jan 1, 2008, at 11:20 AM, rcrchive+18@rcrchive.net wrote:
> Add Array#first and Array#last to the standard library for setting  
> of first and last element.  Behavior should be similar to assigning  
> to [0] and [-1] but not throw an exception for empty Arrays.  In  
> this case the value is simply added.

I don't personally care about the asymmetry of numeric parameters. I  
do care, however, that the case of an empty array changes the size of  
the array while non-empty arrays retain their same length. If these  
methods were added, I would not want to see either change the size of  
an array under any circumstances (or to always change it, i.e. aliases  
for unshift and push).

from Robert Klemme, Wed Jan 02 11:42:31 -0500 2008

2008/1/1, phrogz@mac.com <phrogz@mac.com>:
> I don't personally care about the asymmetry of numeric parameters. I
> do care, however, that the case of an empty array changes the size of
> the array while non-empty arrays retain their same length. If these
> methods were added, I would not want to see either change the size of
> an array under any circumstances (or to always change it, i.e. aliases
> for unshift and push).

IMHO there is no point in adding aliases to #push and #unshift.  The
whole idea of this RCR is to add new functionality.

Please note also, that currently []= does change array length under
certain circumstances:

irb(main):001:0> a=[]
=> []
irb(main):002:0> a[0]=1
=> 1
irb(main):003:0> a
=> [1]
irb(main):004:0> a=[]
=> []
irb(main):005:0> a[10]=1
=> 1
irb(main):006:0> a
=> [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 1]

But then again, since #first= and #last= will typically be used with
non empty Arrays this is less of an issue.

from Gavin Kistner, Wed Jan 02 13:57:08 -0500 2008

On Jan 2, 2008, at 11:42 AM, shortcutter@googlemail.com wrote:
> 2008/1/1, phrogz@mac.com <phrogz@mac.com>:
>> I don't personally care about the asymmetry of numeric parameters. I
>> do care, however, that the case of an empty array changes the size of
>> the array while non-empty arrays retain their same length. If these
>> methods were added, I would not want to see either change the size of
>> an array under any circumstances (or to always change it, i.e.  
>> aliases
>> for unshift and push).
>
> IMHO there is no point in adding aliases to #push and #unshift.  The
> whole idea of this RCR is to add new functionality.

To be clear, I agree. I was simply trying to explain that:
* consistent, predictable, useful behavior is more important to me  
than either piece of functionality
* it seems valid to interpret #last= as either 'overwrite' or 'push'.


> Please note also, that currently []= does change array length under
> certain circumstances:

Granted, but I'm uncertain why you bring it up. That behavior makes  
sense for that method (to me, anyhow). In that case, you are combining  
the fact that Ruby Arrays can autogrow with the message "Please set  
index 'x' to value 'y'."

With #last=, however, my own interpretation is "Change the last item  
in the Array to be 'y'." I would expect either an error or a no-op for  
a zero-length array.

> But then again, since #first= and #last= will typically be used with
> non empty Arrays this is less of an issue.

It's not likely to occur often, but for that very reason I believe  
that it's important to handle it as an exception. "Hey, you just did  
something that (based on Gavin's interpretation of the semantic of  
this method) doesn't make sense; this Array is not what you think it  
is."

Perhaps I don't understand what use case you'd like to use this for,  
though. Perhaps under those circumstances auto-growing the array makes  
sense. Can you describe a semi-real-world use case where you want to  
change (swap out) the last item in an Array? (Or the first.)


Return to top

Copyright © 2006, Ruby Power and Light, LLC