Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Is it possible to have mutable-in-place (associative-)array objects in PHP?

3 views
Skip to first unread message

Robert Maas, http://tinyurl.com/uh3t

unread,
Nov 7, 2009, 6:12:50 AM11/7/09
to
<?php
$countries = array();
$states = array();
$countries['USA'] = $states;
$provinces = array();
$countries['Canada'] = $provinces;
echo "Before: "; print_r($countries);
$states['CA'] = 'California';
$states['OR'] = 'Oregon';
$provinces['BC'] = 'British Columbia';
echo "<br>States: "; print_r($states);
echo "<br>Provinces: "; print_r($provinces);
echo "<br>After: "; print_r($countries);
?>

OUTPUT:
Before: Array ( [USA] => Array ( ) [Canada] => Array ( ) )
States: Array ( [CA] => California [OR] => Oregon )
Provinces: Array ( [BC] => British Columbia )
After: Array ( [USA] => Array ( ) [Canada] => Array ( ) )

I was rather expecting the last line of output to be instead:
After: Array ( [USA] => Array ( [CA] => California [OR] => Oregon )
[Canada] => Array ( [BC] => British Columbia )
)
Not prettyprinted like that, but including the changes I had made
to the second-level arrays.

As you can see, when I add individual states or providences to the
corresponding array, it's not the array that gets changed, it's the
array *variable* that gets changed, and the other reference to
exactly the same array (from the countries array) still sees the
original (empty) array before anything was added. This is unlike
Lisp or Java where if you have an array or vector respectively and
you nest one inside another and then modify the inner one it's
actually *modified* in-place, so that the reference from the parent
array or vector (or hashtable or hashmap) will see the now-changed
object instead of the pre-changed version. Is there any way to get
this Lisp/Java effect of truly mutable-in-place objects in PHP?

It's a real nuisance in PHP to need to go back and manually reset
the array elements in the toplevel array to point to the *new*
versions of the sub-arrays every time the sub-arrays are modified
in order to make the changes appear in the parent array, like this:
<?php
$countries = array();
$states = array();
$countries['USA'] = $states;
$provinces = array();
$countries['Canada'] = $provinces;
echo "Before: "; print_r($countries);
$states['CA'] = 'California';
$countries['USA'] = $states; // Added line, a nuisance!
$states['OR'] = 'Oregon';
$countries['USA'] = $states; // Added line, a nuisance!
$provinces['BC'] = 'British Columbia';
$countries['Canada'] = $provinces; // Added line, a nuisance!
echo "<br>States: "; print_r($states);
echo "<br>Provinces: "; print_r($provinces);
echo "<br>After: "; print_r($countries);
?>

Jerry Stuckle

unread,
Nov 7, 2009, 8:27:03 AM11/7/09
to

This is the way all languages work. When you make a copy, the copy is
independent of the original. Changing either one does not change the
original.

If you want the second one to change, you need to use a reference
instead. But in this case it will greatly complicate your code.


> As you can see, when I add individual states or providences to the
> corresponding array, it's not the array that gets changed, it's the
> array *variable* that gets changed, and the other reference to
> exactly the same array (from the countries array) still sees the
> original (empty) array before anything was added. This is unlike
> Lisp or Java where if you have an array or vector respectively and
> you nest one inside another and then modify the inner one it's
> actually *modified* in-place, so that the reference from the parent
> array or vector (or hashtable or hashmap) will see the now-changed
> object instead of the pre-changed version. Is there any way to get
> this Lisp/Java effect of truly mutable-in-place objects in PHP?
>

This is not Java. Java uses references for objects. If you want a
copy, you must use the objects clone() method. But simple variables in
Java work the same way.

> It's a real nuisance in PHP to need to go back and manually reset
> the array elements in the toplevel array to point to the *new*
> versions of the sub-arrays every time the sub-arrays are modified
> in order to make the changes appear in the parent array, like this:
> <?php
> $countries = array();
> $states = array();
> $countries['USA'] = $states;
> $provinces = array();
> $countries['Canada'] = $provinces;
> echo "Before: "; print_r($countries);
> $states['CA'] = 'California';
> $countries['USA'] = $states; // Added line, a nuisance!
> $states['OR'] = 'Oregon';
> $countries['USA'] = $states; // Added line, a nuisance!
> $provinces['BC'] = 'British Columbia';
> $countries['Canada'] = $provinces; // Added line, a nuisance!
> echo "<br>States: "; print_r($states);
> echo "<br>Provinces: "; print_r($provinces);
> echo "<br>After: "; print_r($countries);
> ?>

That's one way to do it, but there are many others. For instance, don't
even have a $states array - put the data directly into the appropriate
element of the $countries array. Or build the $states array before
assigning it into the $countries array.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstu...@attglobal.net
==================

Tim Roberts

unread,
Nov 7, 2009, 8:36:54 PM11/7/09
to
Jerry Stuckle <jstu...@attglobal.net> wrote:
>
>This is the way all languages work. When you make a copy, the copy is
>independent of the original. Changing either one does not change the
>original.
>
>If you want the second one to change, you need to use a reference
>instead.

You are correct in your assessment, Jerry, but in defense of the original
poster, I'd like to point out that your first sentence is not QUITE
accurate. You yourself said so later on:

>This is not Java. Java uses references for objects. If you want a
>copy, you must use the objects clone() method.

Python is the same here. Had he written that exact code in Python
(basically by removing the dollar signs), it would have worked exactly as
he expected.

So, the issue is not that he has a fundamental misunderstanding of all
languages, but rather that he did not realize that the PHP assignment
operator makes a copy rather than assigning a reference.
--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

Michael Fesser

unread,
Nov 7, 2009, 8:53:35 PM11/7/09
to
.oO(Tim Roberts)

>Jerry Stuckle <jstu...@attglobal.net> wrote:
>>
>>This is the way all languages work. When you make a copy, the copy is
>>independent of the original. Changing either one does not change the
>>original.
>>
>>If you want the second one to change, you need to use a reference
>>instead.
>
>You are correct in your assessment, Jerry, but in defense of the original
>poster, I'd like to point out that your first sentence is not QUITE
>accurate. You yourself said so later on:
>
>>This is not Java. Java uses references for objects. If you want a
>>copy, you must use the objects clone() method.
>
>Python is the same here. Had he written that exact code in Python
>(basically by removing the dollar signs), it would have worked exactly as
>he expected.

I would guess that's just because Python treats arrays as objects
(correct me if I'm wrong - I don't use Python). And today in most
languages objects are implicitly addressed via pointers.

>So, the issue is not that he has a fundamental misunderstanding of all
>languages, but rather that he did not realize that the PHP assignment
>operator makes a copy rather than assigning a reference.

Yes, because arrays in PHP are no objects. If you would use your own
array class, then assigning them to a variable would also create a kind
of reference.

Example:

<?php
$countries = new PHPArray();
$states = new PHPArray();
$provinces = new PHPArray();

$countries['USA'] = $states;
$countries['Canada'] = $provinces;


$states['CA'] = 'California';
$states['OR'] = 'Oregon';
$provinces['BC'] = 'British Columbia';

print_r($countries);
?>

Class PHPArray taken from
http://www.professionelle-softwareentwicklung-mit-php5.de/oop.iterators.arrayaccess.html

Micha

Jerry Stuckle

unread,
Nov 7, 2009, 9:15:07 PM11/7/09
to
Tim Roberts wrote:
> Jerry Stuckle <jstu...@attglobal.net> wrote:
>> This is the way all languages work. When you make a copy, the copy is
>> independent of the original. Changing either one does not change the
>> original.
>>
>> If you want the second one to change, you need to use a reference
>> instead.
>
> You are correct in your assessment, Jerry, but in defense of the original
> poster, I'd like to point out that your first sentence is not QUITE
> accurate. You yourself said so later on:
>

Nope, my statement is 100% accurate. When you make a copy, the copy is
independent of the original.

>> This is not Java. Java uses references for objects. If you want a

>> copy, you must use the objects clone() method.
>
> Python is the same here. Had he written that exact code in Python
> (basically by removing the dollar signs), it would have worked exactly as
> he expected.
>

But in this case, neither Python nor Java is making a copy. It is using
a reference.

> So, the issue is not that he has a fundamental misunderstanding of all
> languages, but rather that he did not realize that the PHP assignment
> operator makes a copy rather than assigning a reference.

Which does not make my statement wrong.

And BTW - even Java makes copies of simple variables. It's when you get
into objects that Java uses references. But in PHP, an array is not an
object. Java vectors are objects.

C. (http://symcbean.blogspot.com/)

unread,
Nov 9, 2009, 6:42:03 AM11/9/09
to
On Nov 8, 1:36 am, Tim Roberts <t...@probo.com> wrote:

> Jerry Stuckle <jstuck...@attglobal.net> wrote:
>
> >This is the way all languages work.  When you make a copy, the copy is
> >independent of the original.  Changing either one does not change the
> >original.
>
> >If you want the second one to change, you need to use a reference
> >instead.
>
> You are correct in your assessment, Jerry, but in defense of the original
> poster, I'd like to point out that your first sentence is not QUITE
> accurate.  You yourself said so later on:
>
> >This is not Java.  Java uses references for objects.  If you want a
> >copy, you must use the objects clone() method.
>
> Python is the same here.  Had he written that exact code in Python
> (basically by removing the dollar signs), it would have worked exactly as
> he expected.
>

PHP (now) uses references for objects too - so if the arrays were
wrapped in an instance of a class then the code would behave as the OP
thinks it should.

> So, the issue is not that he has a fundamental misunderstanding of all
> languages, but rather that he did not realize that the PHP assignment
> operator makes a copy rather than assigning a reference.
> --

No - it's not the assignment operator that is creating the copy - it's
how the interpreter treats arrays.

Try this:

<?php
$inner=array();
$outer=array();
$outer[1]=&$inner;
$inner[1]='hello world';
print_r($outer);

C.


Gordon

unread,
Nov 9, 2009, 7:59:58 AM11/9/09
to
On Nov 7, 11:12 am, seeWebInst...@rem.intarweb.org (Robert Maas,

In PHP version 5+ objects are passed by reference, just like in Java.
But in PHP an array is not an object. This means if you pass it as an
argument or assignment you will get a copy of the array instead of a
reference to it. You can explicitly create a new reference when
assigning by using =& instead of =, and for arguments by using &
$variable instead of $variable.

Curtis Dyer

unread,
Nov 9, 2009, 8:36:05 PM11/9/09
to
On 09 Nov 2009, Gordon <gordon...@ntlworld.com> wrote:

> On Nov 7, 11:12�am, seeWebInst...@rem.intarweb.org (Robert Maas,
> http://tinyurl.com/uh3t) wrote:

<snip>

>> It's a real nuisance in PHP to need to go back and manually
>> reset the array elements in the toplevel array to point to the
>> *new* versions of the sub-arrays every time the sub-arrays are
>> modified in order to make the changes appear in the parent
>> array, like this:

<snipped code>

> In PHP version 5+ objects are passed by reference, just like in
> Java.

This is not quite right. In PHP 5+, objects are not passed by
reference. Object variables' values no longer contain the objects
themsevles, but an object ID. This is more like C, when you pass
an address value as an argument; it can simulate pass-by-
reference, but you are still passing the address by value.

More information about objects and references:
<http://php.net/manual/en/language.oop5.references.php>

> But in PHP an array is not an object. This means if you
> pass it as an argument or assignment you will get a copy of the
> array instead of a reference to it. You can explicitly create a
> new reference when assigning by using =& instead of =, and for
> arguments by using & $variable instead of $variable.

I'm not sure, but it seems like you're advocating call-time pass-
by-reference, which has been deprecated for quite some time. If
you meant declaring PHP function parameters as references while
defining a function/method, that's perfectly valid.

--
Curtis Dyer
<? $x='<? $x=%c%s%c;printf($x,39,$x,39);?>';printf($x,39,$x,39);?>

Gordon

unread,
Nov 10, 2009, 4:26:22 AM11/10/09
to
On Nov 10, 1:36 am, Curtis Dyer <dye...@gmail.com> wrote:
> I'm not sure, but it seems like you're advocating call-time pass-
> by-reference, which has been deprecated for quite some time.  If
> you meant declaring PHP function parameters as references while
> defining a function/method, that's perfectly valid.

Declaring the parameters as references is what I meant.

When you want to assign an array by reference, do $handle =& array.
To pass to a function by reference, do function foo (array &$bar)

Robert Maas, http://tinyurl.com/uh3t

unread,
Nov 10, 2009, 6:23:41 AM11/10/09
to
> From: Jerry Stuckle <jstuck...@attglobal.net>

> This is the way all languages work. When you make a copy, the
> copy is independent of the original. Changing either one does
> not change the original.

Except that I didn't call any function that makes a copy of an
anything. In Lisp or Java, if I do a simple assignment from a
structure slot (such as an element of an array) to a simple
variable, the slot and variable point to exactly the *same* mutable
object. Then if I mutate that object, no copy is made, so the
mutated object is still equally accessible from the local variable
and the slot of the parent structure. Apparently PHP doesn't work
like that, at least not by default, which was surprising to me.
Somewhere hidden from the syntax a copy is being made, so the slot
still points to the *original* unmutated object while all my
mutating work is being done on a *copy* somewhere else in memory.

> If you want the second one to change, you need to use a reference
> instead. But in this case it will greatly complicate your code.

But nobody at your company knows enough about PHP to teach a class,
so why should I believe anything you say? If somebody *else*, such
as Colin or Gordon, tells me how to do it then I'd be more inclined
to believe what they say than the crap you've been telling me.

> This is not Java. Java uses references for objects.

Apparently PHP does too, just that array variables aren't objects
in that sense, which is surprising. FORTRAN is the only other
language I know that doesn't allow pointers to arrays as the
*default* way things are done.

> don't even have a $states array - put the data directly into the
> appropriate element of the $countries array.

That was a simple test example. In the code I'm actually writing, I
have a three-level nested list, where repeating the entire access
path from the top down to the change-location every time I want do
anything would make the code horrendous looking.

> Or build the $states array before assigning it into the
> $countries array.

I don't have that option. I'm loading records from a MySQL database
in whatever sequence the result of a SELECT query gives them to me,
and for each I must find the appropriate path in the tree I'm
building, creating any new sub-tree that I try to traverse for the
very first time, and there's no way to know in advance all the
branches I'll need to build, so building them bottom-up is
impossible. Apparently you just don't have any concept of
algorithms that involve nested lists that form trees that need to
be built incrementally with new sub-trees added almost at random as
new data is encountered. I've been incrementally building even
deeper nested lists as far back as 1970 when I wrote a program to
scan a text file and build a reverse-context tree/histogram,
whereby I start with an empty tree, and an empty back-context, then
go into a loop that works like this:
while (char0 <- input)
treeptr <- rootOfTree
backptr <- topOfBackContext
char <- char0
while (nextptr <- find(treeptr,char))
treeptr <- nextptr
char <- @(backptr++)
treeptr <- addnode(treeptr,char)
push char0 onto BackContext..backptr
As you can see, as it reads characters from the file, as
left-contexts already in the tree are seen a second time, that
context is built deeper back, arbitrary deep back if the same long
string is seen many times. I didn't have Lisp or Java, or even C,
back in 1970 when I wrote that program the first time, so I had to
invent my own list-processing primitives. When I displayed the
resultant tree on-screen, John McCarthy (the fellow who
pre-invented Lisp and had one of his students put the finishing
touches on the design and then actually implement it) happened by
and liked what he saw and offered to hire me if I'd demonstrate
that can write a data-compression program. In 1971 he finally got
around to hiring me.

Jerry Stuckle

unread,
Nov 10, 2009, 7:12:48 AM11/10/09
to
Robert Maas, http://tinyurl.com/uh3t wrote:
>> From: Jerry Stuckle <jstuck...@attglobal.net>
>> This is the way all languages work. When you make a copy, the
>> copy is independent of the original. Changing either one does
>> not change the original.
>
> Except that I didn't call any function that makes a copy of an
> anything. In Lisp or Java, if I do a simple assignment from a
> structure slot (such as an element of an array) to a simple
> variable, the slot and variable point to exactly the *same* mutable
> object. Then if I mutate that object, no copy is made, so the
> mutated object is still equally accessible from the local variable
> and the slot of the parent structure. Apparently PHP doesn't work
> like that, at least not by default, which was surprising to me.
> Somewhere hidden from the syntax a copy is being made, so the slot
> still points to the *original* unmutated object while all my
> mutating work is being done on a *copy* somewhere else in memory.
>

No, you used the assignment operator. This is PHP - not Lisp or Java,
for instance.

>> If you want the second one to change, you need to use a reference
>> instead. But in this case it will greatly complicate your code.
>
> But nobody at your company knows enough about PHP to teach a class,
> so why should I believe anything you say? If somebody *else*, such
> as Colin or Gordon, tells me how to do it then I'd be more inclined
> to believe what they say than the crap you've been telling me.
>

We have not had requests form our customers for PHP classes. Should
there be sufficient demand, we will create the classes.

>> This is not Java. Java uses references for objects.
>
> Apparently PHP does too, just that array variables aren't objects
> in that sense, which is surprising. FORTRAN is the only other
> language I know that doesn't allow pointers to arrays as the
> *default* way things are done.
>

You don't know many languages, do you?

>> don't even have a $states array - put the data directly into the
>> appropriate element of the $countries array.
>
> That was a simple test example. In the code I'm actually writing, I
> have a three-level nested list, where repeating the entire access
> path from the top down to the change-location every time I want do
> anything would make the code horrendous looking.
>

Glad I'm NOT working on your worthless project!

Then redesign your script.

And who really cares about your claim of John McCarthy hiring you? I
sure don't. And I doubt anyone else here does, either (if anyone
believes you, that is).

Robert Maas, http://tinyurl.com/uh3t

unread,
Nov 16, 2009, 7:13:38 AM11/16/09
to
> From: "C. (http://symcbean.blogspot.com/)" <colin.mckin...@gmail.com>

> PHP (now) uses references for objects too - so if the arrays were
> wrapped in an instance of a class then the code would behave as
> the OP thinks it should.

Somebody else said if I use the reference-sharing operator instead
of the regular assignment operator, it'll simply copy the link to
the zval instead of copying the entire array and making a new zval
pointing to it. So I don't think I'll need to make an array class
like you proposed.

> it's not the assignment operator that is creating the copy - it's
> how the interpreter treats arrays.

Somebody else said otherwise.

> Try this:
> <?php
> $inner=3Darray();
> $outer=3Darray();
> $outer[1]=3D&$inner;
> $inner[1]=3D'hello world';
> print_r($outer);

ERROR: Unexpected end-of-file in middle of PHP script, likely '?>' missing?
Let's see what happens if I actually try that exactly as you gave it:
If I try to run it on my shell account, it gives 500 internal server error.
Let me try it on my development site for PHP/MySQL scripts:
Parse error: syntax error, unexpected T_STRING in
/www/oxyhost.com/c/a/l/calrobert/htdocs/tmpB16.php on line 2
I don't think it likes those '3D' strings between the equal sign
and the 'array' word. What character did you really intend there?

> lisp
CMU Common Lisp 19c Release (19C), running on shell0.rawbw.com
With core: /usr/local/lib/cmucl/lib/lisp.core
Dumped on: Wed, 2005-11-16 17:18:11-08:00 on snapdragon.csl.sri.com
See <http://www.cons.org/cmucl/> for support information.
Loaded subsystems:
Python 1.1, target Intel x86
CLOS based on Gerd's PCL 2004/04/14 03:32:47
* (code-char (parse-integer "3D" :RADIX 16)) => #\=

That doesn't make a lot of sense that you'd have another equal sign
but coded in hexadecimal instead of verbatim.
Can you please post your proposed script on a Web site as a plain
text file with extension .txt and post the URL of it to a followup
article, and I'll go that URL and download the .txt file and see
what's there and rename to .php and see what happens when I run it?

Hmm, maybe you're using the notation =3D (with that = sign as a
prefix to the hexadecimal, part of the syntax for one character) to
indicate the = character, so your script should read:

> <?php
> $inner=array();
> $outer=array();
> $outer[1]=&$inner;
> $inner[1]='hello world';
> print_r($outer);

Shit, even without the closing tag to exit the script back to HTML,
it still works:
Array ( [1] => Array ( [1] => hello world ) )
Let me try the development server with good diagnostics also:
Array ( [1] => Array ( [1] => hello world ) )
Hmm, apparently it's *not* an error to go from HTML into a PHP
script and *never* get back to HTML before end of file??
Did you actually *know* that when you sent me the script?
Or did you accidently leave out the closing script tag and by
chance it was actually OK to do that?

Anyway, your example works because of what the other person said,
*not* because of what you incorrectly said. I think you were trying
to play a practical joke on me.

By the way, there's a big piece of code that I wrote that isn't
scalable to millions of accounts, maybe not even well scalable to
thousands of accounts. If and when I get hundreds of users I'll
need to re-write that code. But I think I'll just pay my users to
write the code for me instead of doing it all myself.

Gordon Burditt

unread,
Nov 16, 2009, 2:06:49 PM11/16/09
to
>> Try this:
>> <?php
>> $inner=3Darray();
>> $outer=3Darray();
>> $outer[1]=3D&$inner;
>> $inner[1]=3D'hello world';
>> print_r($outer);
>
>ERROR: Unexpected end-of-file in middle of PHP script, likely '?>' missing?
>Let's see what happens if I actually try that exactly as you gave it:
>If I try to run it on my shell account, it gives 500 internal server error.
>Let me try it on my development site for PHP/MySQL scripts:
> Parse error: syntax error, unexpected T_STRING in
> /www/oxyhost.com/c/a/l/calrobert/htdocs/tmpB16.php on line 2
>I don't think it likes those '3D' strings between the equal sign
>and the 'array' word. What character did you really intend there?

The code has been MIMEd. Replace equal 3 D with an equal sign.
Occasionally you will see other mangling like equal 0 A which becomes
a newline. This happens a lot on posted URLs.

>Anyway, your example works because of what the other person said,
>*not* because of what you incorrectly said. I think you were trying
>to play a practical joke on me.

Don't assume that. Some news posters MIME stuff automatically if
they see certain characters or sometimes unconditionally, and
the poster may not be aware of it. Some newsreaders also transform
this back automatically.

Robert Maas, http://tinyurl.com/uh3t

unread,
Nov 19, 2009, 2:29:38 PM11/19/09
to
> From: Gordon <gordon.mc...@ntlworld.com>

> In PHP version 5+ objects are passed by reference, just like in Java.

I checked just now, and all the free PHP/MySQL hosting sites I'm
experimenting with, as well as where my shell account is, are all
running some version 5.1.x or 5.2.x, so I don't have to worry about
major incompatility when I develop a script on one site then copy
it to another site.

> But in PHP an array is not an object. This means if you pass it
> as an argument or assignment you will get a copy of the array
> instead of a reference to it.

That disagreed with what other people said.

> You can explicitly create a new reference when assigning by using

> =3D& instead of =3D, and for arguments by using & $variable instead
> of $variable.

I take it when you say "=3D" you really mean "=".

I get a feeling of having already responded to this. Did I
mistakenly download two copies of your article, and reply to one
copy previously and now this second copy? I wish I knew of some
Web-based system whereby I can keep track of threads I'm interested
in, split sub-threads if some branches have gone worthless while
others are still active, find all new articles in the still-good
threads, always find direct followups to what I posted myself and
add such sub-threads to the active set if not already active, and
keep track of which articles I've already downloaded so I don't
mistakely download them again, etc. etc. Right now (and in the
foreseeable future) I'm too busy on NewEco to write all that myself.

0 new messages