Best arrays questions in May 2011

Why array implements IList?

24 votes

See the definition of System.Array class

public abstract class Array : IList, ...

Theoretically, I should be able to write this bit and be happy

int[] list = new int[] {};
IList iList = (IList)list;

I also should be able to call any method from the iList

 ilist.Add(1); //exception here

My question is not why I get an exception, but rather why Array implements IList?

Because an array allows fast access by index, and IList/IList<T> is are the only collection interfaces that support this. So perhaps your real question is "Why is there no interface for constant collections with indexers?" And to that I have no answer.

There are no readonly interfaces for collections either. And I'm missing those even more than a constant sized with indexers interface.

IMO there should be several more (generic) collection interfaces depending on the features of a collection. And the names should have been different too, List for something with an indexer is really stupid IMO.

  • Just Enumeration IEnumerable<T>
  • Readonly but no indexer (.Count, .Contains,...)
  • Resizable but no indexer, i.e. set like (Add, Remove,...) current ICollection<T>
  • Readonly with indexer (indexer, indexof,...)
  • Constant size with indexer (indexer with a setter)
  • Variable size with indexer (Insert,...) current IList<T>

I think the current collection interfaces are bad design. But since they have properties telling you which methods are valid(and this is part of the contract of these methods) it doesn't break the substitution principle.

what does [:] in python mean?

18 votes

Hi,

I'm analyzing some python code and i don't know what

pop = population[:]

means. Is it something like array lists in Java or like a bi-dimensional array? Could appreciate some help, thanks.

It's a slicing, and what it does depends on the type of population. If population is a list, this line will create a copy of the list. For an object of type tuple or a str, it will do nothing (the line will do the same without [:]), and for a (say) NumPy array, it will create a new view to the same data.

Bug or hack? $GLOBALS.

16 votes
$GLOBALS["items"] = array('one', 'two', 'three', 'four', 'five' ,'six', 'seven');
$alter = &$GLOBALS["items"]; // Comment this line
foreach($GLOBALS["items"] as $item) {
  echo get_item_id();
}

function get_item_id(){
  var_dump(key($GLOBALS["items"]));
}

Check output of this code, with commented and uncommented second line. My result(PHP 5.3.0). With second line

int(1) int(2) int(3) int(4) int(5) int(6) NULL

Without second line:

int(1) int(1) int(1) int(1) int(1) int(1) int(1)

Why so strange result?

Here is a possible explanation:

We know that foreach always loops over a copy of the array if it is not referenced:

Unless the array is referenced, foreach operates on a copy of the specified array and not the array itself. foreach has some side effects on the array pointer.

That means that the internal pointer of the original array is not changed and key() will always return the same value (as we can see when we comment out the line). And indeed if we do a var_dump($GLOBALS), we get:

 ["items"]=>
  array(7) {
    [0]=>
    string(3) "one"
    [1]=>
    string(3) "two"
    [2]=>
    string(5) "three"
    [3]=>
    string(4) "four"
    [4]=>
    string(4) "five"
    [5]=>
    string(3) "six"
    [6]=>
    string(5) "seven"
  }

(no reference)

But as soon as we generate a reference to the array (with $alter), $GLOBALS['items'] becomes a reference too, because both entries have to point to the same array:

 ["items"]=>
  &array(7) {
    [0]=>
    string(3) "one"
    [1]=>
    string(3) "two"
    [2]=>
    string(5) "three"
    [3]=>
    string(4) "four"
    [4]=>
    string(4) "five"
    [5]=>
    string(3) "six"
    [6]=>
    string(5) "seven"
  }
  ["alter"]=>
  &array(7) {
    [0]=>
    string(3) "one"
    [1]=>
    string(3) "two"
    [2]=>
    string(5) "three"
    [3]=>
    string(4) "four"
    [4]=>
    string(4) "five"
    [5]=>
    string(3) "six"
    [6]=>
    string(5) "seven"
  }

Hence, the foreach loop does iterate over the original array and changes the internal pointer, which affects key().


To sum up: It is a problem with references, not with $GLOBALS.