# Only variables can be passed by reference

- Thread: https://externals.io/message/79412
- Original archive: https://news-web.php.net/php.internals/79412
- Started by Yasuo Ohgaki on 2014-12-04T08:28:03+00:00
- Messages: 30
- Page 1 of 2: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/79412.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #79412 — Yasuo Ohgaki — 2014-12-04T08:28:03+00:00

URL: https://externals.io/message/79412#79412

Hi all,

I think we can get rid of this error now when literal is returned.
The reason we have `E_STRICT` error is that legacy PHP didn't
support this, I suppose.

http://3v4l.org/8fISj

Is it possible to allow literal as referenced parameter for PHP7?
It's better to remove needless restrictions where it is possible.
HHVM seems already support this.

http://3v4l.org/t79rF

Any comments?

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #79414 — Andrea Faulds — 2014-12-04T08:32:50+00:00

URL: https://externals.io/message/79412#79414 · In reply to: #79412

> 
> 
> Hi all,
> 
> I think we can get rid of this error now when literal is returned.
> The reason we have `E_STRICT` error is that legacy PHP didn't
> support this, I suppose.
> 
> http://3v4l.org/8fISj

Hmm, I think there’s some logic to having a warning anyway. If a parameter is taken by reference, then it’s presumably going to be modified. So if you pass something that isn’t a variable (and therefore the modified result can’t be accessed) to a by-reference parameter, it doesn’t really make sense.
--
Andrea Faulds
http://ajf.me/

---

## #79415 — Christian Stoller — 2014-12-04T08:47:02+00:00

URL: https://externals.io/message/79412#79415 · In reply to: #79414

From: Andrea Faulds [mailto:ajf@ajf.me], Thursday, December 04, 2014 9:33 AM
>
> > […]
>
> Hmm, I think there’s some logic to having a warning anyway. 
> If a parameter is taken by reference, then it’s > presumably 
> going to be modified. So if you pass something that isn’t
> a variable (and therefore the modified result can’t be
> accessed) to a by-reference parameter, it doesn’t really
> make sense.
> --
> Andrea Faulds
> http://ajf.me/
> 

I like Yasuo's proposal, because the developer who's passing a
non-variable by reference knows that the change will be lost. But this
could be desired as Yasuo's example shows.

I wished many times that this would be possible...

---

## #79416 — Yasuo Ohgaki — 2014-12-04T08:48:07+00:00

URL: https://externals.io/message/79412#79416 · In reply to: #79414

Hi Andrea,



> > […]
>
> Hmm, I think there’s some logic to having a warning anyway. If a parameter
> is taken by reference, then it’s presumably going to be modified. So if you
> pass something that isn’t a variable (and therefore the modified result
> can’t be accessed) to a by-reference parameter, it doesn’t really make
> sense.


I agree. It might be a bug in user code simply. However, example code
illustrates that there is valid usage.
Static method may return literal, default for some config, etc.

http://3v4l.org/jKXpb

We may use @ or get rid of `E_STRICT` altogether. I wonder if we really need
 `E_STRICT` error here.

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #79418 — Yasuo Ohgaki — 2014-12-04T10:08:54+00:00

URL: https://externals.io/message/79412#79418 · In reply to: #79412

Hi all,



> I think we can get rid of this error now when literal is returned.
> The reason we have `E_STRICT` error is that legacy PHP didn't
> support this, I suppose.
>
> http://3v4l.org/8fISj
>
> Is it possible to allow literal as referenced parameter for PHP7?
> It's better to remove needless restrictions where it is possible.
> HHVM seems already support this.
>
> http://3v4l.org/t79rF
>
> Any comments?
>

I made a little better sample code.

http://3v4l.org/d51DQ

I would like to hear opinions from engine experts.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #79419 — Yasuo Ohgaki — 2014-12-04T10:38:52+00:00

URL: https://externals.io/message/79412#79419 · In reply to: #79418

Hi all,

Sorry for multiple posts. This would be the last one.



> 
>
> > […]
>
> I made a little better sample code.
>
> http://3v4l.org/d51DQ
>
> I would like to hear opinions from engine experts.


Yet another sample code. This cannot be executed on 3v4l.org for security
reasons.

<?php
$sock = fsockopen('www.php.net', '80');
var_dump($sock);

$socks = array($sock);
var_dump(stream_select($socks, $socks, $socks, 1));

//var_dump(stream_select(array($sock), array($sock), array($sock), 1));
//Fatal error: Only variables can be passed by reference in
/home/yohgaki/tmp/ttt.php on line 8
?>

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #79424 — Andrea Faulds — 2014-12-04T12:26:06+00:00

URL: https://externals.io/message/79412#79424 · In reply to: #79419

> 
> 
> 
> Yet another sample code. This cannot be executed on 3v4l.org for security
> reasons.
> 
> <?php
> $sock = fsockopen('www.php.net', '80');
> var_dump($sock);
> 
> $socks = array($sock);
> var_dump(stream_select($socks, $socks, $socks, 1));
> 
> //var_dump(stream_select(array($sock), array($sock), array($sock), 1));
> //Fatal error: Only variables can be passed by reference in
> /home/yohgaki/tmp/ttt.php on line 8
> ?>

Using stream_select without real variables like that is weird, what’s the point? You’ve discarded the read/write/error information, all the return value tells you is that *something* changed.

--
Andrea Faulds
http://ajf.me/

---

## #79429 — Kalle Sommer Nielsen — 2014-12-04T19:58:09+00:00

URL: https://externals.io/message/79412#79429 · In reply to: #79412

Hi Yasuo

2014-12-04 9:28 GMT+01:00 Yasuo Ohgaki <yohgaki@ohgaki.net>:
> Any comments?
>
> Regards,
>
> --
> Yasuo Ohgaki
> yohgaki@ohgaki.net

I think we should solve these on a case-by-case basis, I can think of
one reason why the warning exists, and that is because it modifies the
array pointer and the argument is sent by reference. But I think we
can safely remove the warning if the parameter was not sent by
reference, as then we would expect the user to use the return value of
 `array_pop()` to assign the value from. I don't think we should remove
warnings if you pass a statically value to it, sure some APIs can
return a variable length/dynamic array but then I think they should be
referenced into a variable and then passed to the function as they are
most likely going to be used later, I can't really think of a case
where it would be useful to send a return value of some API call to
 `array_multisort()` and then use the boolean true or false to check if
it was a successful call for example..

For functions like `next()` that only supports taking the argument by
reference, this should remain (since the return value is the internal
array pointer position).

I went over the manual and the following should remain that warning:
 `array_multisort()`
 `array_push()`
 `array_shift()`
 `array_unshift()`
 `array_walk()`
 `array_walk_recursive()`
 `asort()`
 `arsort()`
each()
 `ksort()`
 `krsort()`
 `natsort()`
 `natcasesort()`
 `reset()` -- Debatable though (does not many any sense, but if `current()`
and family is, and this is not, it will make it inconsistent)
 `rsort()`
 `shuffle()`
 `sort()`
 `usort()`
 `uasort()`
 `uksort()`


And the following can have the warning removed if the argument is not
passed by reference:
 `array_pop()`
 `array_splice()`
 `current()` -- Debatable though
 `end()` -- Debatable though (use array deferencing?)
 `extract()`
 `key()` -- Same as `current()`
 `next()` -- Same as `current()`
 `prev()` -- Same as `current()`


(Note, there is probably some I have missed, as I only looked for the
&$array in the prototype of the functions listed above)


Thoughts?


-- 
regards,

Kalle Sommer Nielsen
kalle@php.net

---

## #79430 — Levi Morrison — 2014-12-04T21:34:19+00:00

URL: https://externals.io/message/79412#79430 · In reply to: #79429

> Thoughts?

The only reason to take a parameter by reference is because you modify
the variable that the caller is passing in. Passing in constants is
*almost certainly* an error. I would rather have the warnings than
remove them.

---

## #79431 — Yasuo Ohgaki — 2014-12-04T22:02:09+00:00

URL: https://externals.io/message/79412#79431 · In reply to: #79424

Hi Andrea, Stas and all



> > […]
>
> Using stream_select without real variables like that is weird, what’s the
> point? You’ve discarded the read/write/error information, all the return
> value tells you is that *something* changed.


There are 2 points.
It does not have to be module functions. User may define function which has
similar to `stream_select()`.

int stream_select ( array &$read , array &$write , array &$except , int
$tv_sec [, int $tv_usec = 0 ] )

This kind of signature requires $tv_sec. If $write and $except can
null(NULL) or empty array(array() or []), but it does not allowed.

Even when there is parameter to pass, user has to create variable always.

select_select([$a], [$b], [$c], 10);

fails with E_ERROR, while

$x = [$a];
$y = [$b];
$z = [$c];
stream_select($x, $y, $z, 10);

works, but It does not look nice.

Stas points out "these are constant".
It is a kind of constant since array(1,2,3) is array literal and value
never changes.
I'm not sure how literals are handles in Zend engine, but it may use the
value as
referenced parameter.

array_splice(array(1,2,3,4), 2);

Code like this is useful to get certain part of config, etc.
Nobody writes code like above directly. If function returns literal and
passed as
referenced argument, then PHP raises error.

Please take a look at this code

http://3v4l.org/qUDOv

Raising errors for this kind of code is not good. IMHO.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #79432 — Levi Morrison — 2014-12-04T23:14:31+00:00

URL: https://externals.io/message/79412#79432 · In reply to: #79431

> Even when there is parameter to pass, user has to create variable always.
>
> select_select([$a], [$b], [$c], 10);
>
> fails with E_ERROR, while
>
> $x = [$a];
> $y = [$b];
> $z = [$c];
> stream_select($x, $y, $z, 10);
>
> works, but It does not look nice.

From the documentation: "Also do not forget that those arrays are
passed by reference and will be modified after `stream_select()`
returns."

These modify by reference; ignoring this is almost *certainly* a bug
on your part.

---

## #79433 — Andrea Faulds — 2014-12-04T23:18:50+00:00

URL: https://externals.io/message/79412#79433 · In reply to: #79429

> 
> 
> I think we should solve these on a case-by-case basis, I can think of
> one reason why the warning exists, and that is because it modifies the
> array pointer and the argument is sent by reference. But I think we
> can safely remove the warning if the parameter was not sent by
> reference, as then we would expect the user to use the return value of
> `array_pop()` to assign the value from. I don't think we should remove
> warnings if you pass a statically value to it, sure some APIs can
> return a variable length/dynamic array but then I think they should be
> referenced into a variable and then passed to the function as they are
> most likely going to be used later, I can't really think of a case
> where it would be useful to send a return value of some API call to
> `array_multisort()` and then use the boolean true or false to check if
> it was a successful call for example..

Doing it case-by-case seems like the most pragmatic approach.

That being said, I’m not sure there are many cases, if any, for which I don’t think a warning should be shown. It feels like an abuse of the internal array pointer functions (next/prev/key/extract/etc.) to use them like this. It’d probably be better to add non-by-ref functions that do the same thing instead.

--
Andrea Faulds
http://ajf.me/

---

## #79434 — Yasuo Ohgaki — 2014-12-04T23:34:48+00:00

URL: https://externals.io/message/79412#79434 · In reply to: #79432

Hi Levi,



> > […]
>
> From the documentation: "Also do not forget that those arrays are
> passed by reference and will be modified after `stream_select()`
> returns."
>
> These modify by reference; ignoring this is almost *certainly* a bug
> on your part.


I'm not discussing about how to use `stream_select()`, but it's signature
and parameter passing behavior. It was wrong example apparently.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #79435 — Chris Wright — 2014-12-04T23:46:38+00:00

URL: https://externals.io/message/79412#79435

Forgot to cc list, see below

---------- Forwarded message ----------
From: "Chris Wright" <cw@daverandom.com>
Date: 4 Dec 2014 14:09
Subject: Re: [PHP-DEV] Re: Only variables can be passed by reference
To: "Andrea Faulds" <ajf@ajf.me>
Cc:

> 
> > […]
security
> > […]
the point? You’ve discarded the read/write/error information, all the
return value tells you is that *something* changed.
> > […]
>
> While I'm undecided on this change (leaning towards "no"), there is a
more useful example with `stream_select()`:
>
> $socks = array($sock);
> var_dump(stream_select($socks, $socks, NULL, 1));
>
> It is rare that anything actually uses OOB data in the real world, more
often than not `stream_select()` is preceded by a line like $e = NULL;
>
> I could maybe get behind this for specifically permitting literal `NULL` to
be passed, as is often the convention for out params in C, where passing a
 `NULL` pointer is permitted and handled as "I don't want this data".
>
> Another example of where this could be useful is `stream_socket_client()`,
where you want to specify timeout/flags/context but don't care about
errno/errstr, so you could pass literal `NULL` to these instead of having to
declare a couple of trash variables.
>
> That said, the use cases above would probably be better served by named
parameters.
>
> Thanks, Chris
>
> > […]

---

## #79437 — Yasuo Ohgaki — 2014-12-05T01:07:03+00:00

URL: https://externals.io/message/79412#79437 · In reply to: #79412

Hi all,



> I think we can get rid of this error now when literal is returned.
> The reason we have `E_STRICT` error is that legacy PHP didn't
> support this, I suppose.
>
> http://3v4l.org/8fISj
>
> Is it possible to allow literal as referenced parameter for PHP7?
> It's better to remove needless restrictions where it is possible.
> HHVM seems already support this.
>
> http://3v4l.org/t79rF
>
> Any comments?
>

It may be better to focus on return value from functions/methods.

There are cases that return values are better to be treated as usual
variables. For example,

<?php
function f1(&$v) {}
function f2() {$a = array(1,2,3); return $a; }

f1(f2());
?>

http://3v4l.org/2prWX

 `E_STRICT` error here is too much. IMHO.
I think this kind of code should be allowed without errors rather than
forcing users to save return value to variable. e.g.

$v = f2();
f1($v);

Making scalar to array may be stay as it is now.

<?php
function f1(&$v) {}
function f2() {$a = array(1,2,3); return $a; }

// Both are Fatal error: Only variables can be passed by reference
f1((array)f2());
f1(array(f2()));
?>

http://3v4l.org/Ob1o2

HHVM behavior is interesting. It treats return value as usual variable, but
HHVM does not allow casts.

<?php
function f1(&$v) {}
function f2() {$a = array(1,2,3); return $a; }

f1((bool)f2());
?>

http://3v4l.org/J4Q8e

Any comments?

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #79439 — Rowan Collins — 2014-12-05T09:12:37+00:00

URL: https://externals.io/message/79412#79439 · In reply to: #79437

>Hi all,
>
>On Thu, Dec 4, 2014 at 5:28 PM, Yasuo Ohgaki <yohgaki@ohgaki.net>
>wrote:
>
> > […]
>
>It may be better to focus on return value from functions/methods.
>
>There are cases that return values are better to be treated as usual
>variables. For example,
>
><?php
>function f1(&$v) {}
>function f2() {$a = array(1,2,3); return $a; }
>
>f1(f2());
>?>
>
>http://3v4l.org/2prWX
>
>E_STRICT error here is too much. IMHO.
>I think this kind of code should be allowed without errors rather than
>forcing users to save return value to variable. e.g.
>
>$v = f2();
>f1($v);

The author of function f1() presumably designed it to apply some change to $v, rather than executing only for its side effects and return value. If the caller wants to ignore this design, they can, but they are not using the function as it was designed. If they pass a function return straight into it, they have no way of capturing the change to $v which the author intended them to see.

 `E_STRICT` seems like the perfect output for that: "what you're doing will work, but it's probably not the best idea, and there's an easy tweak you might want to consider".

You might want some way of saying "no, I really meant to do that" (more elegantly than the @ operator), but `E_STRICT` is full of hints like this that border on coding style, so if you don't like that, just mask it out of error_reporting.

That's my 2 pence, anyway.
-- 
Rowan Collins
[IMSoP]

---

## #79440 — Eugene — 2014-12-05T09:18:36+00:00

URL: https://externals.io/message/79412#79440 · In reply to: #79419

Hi Yasuo,



> Hi all,
>
> Sorry for multiple posts. This would be the last one.
>
> 
>
> > […]
>
>
> Yet another sample code. This cannot be executed on 3v4l.org for security
> reasons.
>
> <?php
> $sock = fsockopen('www.php.net', '80');
> var_dump($sock);
>
> $socks = array($sock);
> var_dump(stream_select($socks, $socks, $socks, 1));
>
> //var_dump(stream_select(array($sock), array($sock), array($sock), 1));
> //Fatal error: Only variables can be passed by reference in
> /home/yohgaki/tmp/ttt.php on line 8
> ?>
>
> Regards,
>
> --
> Yasuo Ohgaki
> yohgaki@ohgaki.net
>


Here is a real use case where removing this error would be beneficial:
https://github.com/mongofill/mongofill/issues/23#issuecomment-36469658


-- 
Thank you and best regards,
Eugene Leonovich

---

## #79452 — Yasuo Ohgaki — 2014-12-06T03:03:41+00:00

URL: https://externals.io/message/79412#79452 · In reply to: #79439

Hi Rowan,

On Fri, Dec 5, 2014 at 6:12 PM, Rowan Collins <rowan.collins@gmail.com>
wrote:

> The author of function f1() presumably designed it to apply some change to
> $v, rather than executing only for its side effects and return value. If
> the caller wants to ignore this design, they can, but they are not using
> the function as it was designed. If they pass a function return straight
> into it, they have no way of capturing the change to $v which the author
> intended them to see.


The value supplied to f1() is return value.
In languages, there are literal, constant and variable. Return value is
variable.
It's better to keep basic rule. IMHO.

$top = array_pop(f2());

is better than

$v = f2();
$top = array_pop($v);

Is there anyone who likes latter?
Are there any other languages behave like PHP?

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #79453 — Patrick Schaaf — 2014-12-06T08:52:50+00:00

URL: https://externals.io/message/79412#79453 · In reply to: #79452

Am 06.12.2014 04:04 schrieb "Yasuo Ohgaki" <yohgaki@ohgaki.net>:
>
> $top = array_pop(f2());
>
> is better than
>
> $v = f2();
> $top = array_pop($v);
>
> Is there anyone who likes latter?

It is bad practise either way, having poor f2() build up a whole array that
is then immediately thrown away. The second case is worse due to missing an
unset($v), keeping the array around for eternity...

I personally do find it annoying to "need" a variable there, just because
the outer called function happens to take a parameter as reference - which
is not visible at the calling place at first glance, thus making me wonder,
when only looking there, what the hell that scratch variable is supposed to
accomplish...

In practise this part of the issue didn't arise that often, compared to the
other part: only being able to return variables by reference. Concretely,
that hit me when writing return-by-reference offsetGet() methods that
sometimes need to return null. Not that bad, in a sense, because the
scratch-null-holding-variable is contained in the place where it belongs,
the offsetGet method itself - but nevertheless strange...

best regards
   Patrick

---

## #79454 — Joe Watkins — 2014-12-06T09:26:43+00:00

URL: https://externals.io/message/79412#79454 · In reply to: #79452

> Hi Rowan,
> 
> On Fri, Dec 5, 2014 at 6:12 PM, Rowan Collins <rowan.collins@gmail.com>
> wrote:
> 
> > […]
> 
> 
> The value supplied to f1() is return value.
> In languages, there are literal, constant and variable. Return value is
> variable.
> It's better to keep basic rule. IMHO.
> 
> $top = array_pop(f2());
> 
> is better than
> 
> $v = f2();
> $top = array_pop($v);
> 
> Is there anyone who likes latter?
> Are there any other languages behave like PHP?
> 
> Regards,
> 
> --
> Yasuo Ohgaki
> yohgaki@ohgaki.net

A return value that has no references is a temporary variable, you
forgot about temporary variables.

There is a basic, simple rule; temporary variables cannot be used by
reference, which is perfectly logical since there are no references to
temporary variables, that's what makes them temporary.

I don't see the need to change it.

Cheers
Joe

---

## #79455 — Christoph Becker — 2014-12-06T11:00:17+00:00

URL: https://externals.io/message/79412#79455 · In reply to: #79452

Yasuo Ohgaki wrote:

> In languages, there are literal, constant and variable. Return value is
> variable.
> It's better to keep basic rule. IMHO.
> 
> $top = array_pop(f2());
> 
> is better than
> 
> $v = f2();
> $top = array_pop($v);
> 
> Is there anyone who likes latter?
> Are there any other languages behave like PHP?

IMHO, the first snippet is confusing (the second as well, if $v is not
used in the following code).  Actually, you don't want to pop the top of
the stack, but you want to simply get it without altering the stack at
all.  Therefore it seems reasonable to use a function called array_top()
(or so) which takes its argument by value.

-- 
Christoph M. Becker

---

## #79457 — Rowan Collins — 2014-12-06T14:25:42+00:00

URL: https://externals.io/message/79412#79457 · In reply to: #79452

> Hi Rowan,
>
> On Fri, Dec 5, 2014 at 6:12 PM, Rowan Collins <rowan.collins@gmail.com 
> <mailto:rowan.collins@gmail.com>> wrote:
>
>     The author of function f1() presumably designed it to apply some
>     change to $v, rather than executing only for its side effects and
>     return value. If the caller wants to ignore this design, they can,
>     but they are not using the function as it was designed. If they
>     pass a function return straight into it, they have no way of
>     capturing the change to $v which the author intended them to see.
>
>
> The value supplied to f1() is return value.
> In languages, there are literal, constant and variable. Return value 
> is variable.

No, a return value is a value - it is the result of some computation 
which has not yet been assigned to a variable. This is perhaps more 
obvious with an operator: "1 + 2" is not a variable, it is the value 3; 
internally, a temporary variable is probably used to hold that value, 
but that temporary variable is never accessible to the programmer. If 
you have function add($a, $b) { return $a + $b; }, then add(1,2) is 
still not a variable in any meaningful sense.

> It's better to keep basic rule. IMHO.
>
> $top = array_pop(f2());
>
> is better than
>
> $v = f2();
> $top = array_pop($v);
>
> Is there anyone who likes latter?

 `array_pop()` is a stack-manipulation function, so the latter is the 
correct use, with $v going on to be used as the rest of the stack. If 
you're using it for something other than stack manipulation, neither is 
correct, because it's the wrong choice of function.

> Are there any other languages behave like PHP?

In some languages - e.g. Pascal, Transact-SQL - the most common form of 
sub-routine is a "procedure", which doesn't return a value in the way 
that a function does, but instead has "input" and "output" parameters. 
Supplying something other than a variable to an "output" parameter would 
clearly be just as wrong as putting it on the left-hand side of an 
assignment (e.g. f2() = f1()).

Even in languages with functions or methods rather than procedures as 
their main building block, it's common to have output-only parameters to 
capture multiple return values without the need for a complex return 
type. For instance, it might be legal to pass the return value of 
malloc() in C straight to something requiring a pointer to some memory, 
but it's almost certainly a mistake to do so, because you would have no 
way of accessing the buffer afterwards.

-- 
Rowan Collins
[IMSoP]

---

## #79458 — Rowan Collins — 2014-12-06T14:29:21+00:00

URL: https://externals.io/message/79412#79458 · In reply to: #79455

> Yasuo Ohgaki wrote:
>
> > […]
> IMHO, the first snippet is confusing (the second as well, if $v is not
> used in the following code).  Actually, you don't want to pop the top of
> the stack, but you want to simply get it without altering the stack at
> all.  Therefore it seems reasonable to use a function called array_top()
> (or so) which takes its argument by value.

I think this hits the nail on the head: most times when you're trying to 
pass a literal or return to a by-ref parameter, it's because the 
function you're using isn't actually the right fit for what you're 
trying to do - either because it's badly designed (arguably the case 
with `stream_select()`) or because you're using it for a purpose it wasn't 
intended for (e.g. `array_pop()` if you're not going to use the rest of 
the stack).

For user-defined functions, one reaction to the `E_STRICT` notice might be 
to realise that you don't actually need a by-ref parameter there anyway, 
so you can remove the & in the declaration, and everything's fine. For 
internal functions, it may mean that we're lacking something useful 
(e.g. accessing first and last elements of arrays without side-effects).

-- 
Rowan Collins
[IMSoP]

---

## #79459 — Rowan Collins — 2014-12-06T14:38:44+00:00

URL: https://externals.io/message/79412#79459 · In reply to: #79435

> Forgot to cc list, see below
>
> ---------- Forwarded message ----------
> From: "Chris Wright" <cw@daverandom.com>
> Date: 4 Dec 2014 14:09
> Subject: Re: [PHP-DEV] Re: Only variables can be passed by reference
> To: "Andrea Faulds" <ajf@ajf.me>
> Cc:
>
> > […]
> security
> > […]
> the point? You’ve discarded the read/write/error information, all the
> return value tells you is that *something* changed.
> > […]
> more useful example with `stream_select()`:
> > […]
> often than not `stream_select()` is preceded by a line like $e = NULL;
> > […]
> be passed, as is often the convention for out params in C, where passing a
> `NULL` pointer is permitted and handled as "I don't want this data".
> > […]
> where you want to specify timeout/flags/context but don't care about
> errno/errstr, so you could pass literal `NULL` to these instead of having to
> declare a couple of trash variables.
> > […]
> parameters.
>

Perhaps if a parameter is optional and defaulted to null, a literal null 
could be allowed even if it would normally be by-ref? This would match 
the behaviour of type-hinting, e.g.

function foo(Bar $bar=null) { ... }
foo(null);

function foo(&$bar=null) { ... }
foo(null);

The point being that you could then skip over by-ref parameters in some 
of the examples above, e.g. allow this:

$sock = fsockopen('www.php.net', '80');
$socks = array($sock);
stream_select($socks, null, null, 1);

Named parameters would make this look prettier, but you'd need to make 
the parameters optional in the declaration anyway.

-- 
Rowan Collins
[IMSoP]

---

## #79460 — Yasuo Ohgaki — 2014-12-06T22:25:50+00:00

URL: https://externals.io/message/79412#79460 · In reply to: #79457

Hi Rowan,

On Sat, Dec 6, 2014 at 11:25 PM, Rowan Collins <rowan.collins@gmail.com>
wrote:

> 
>
> > […]
>
> No, a return value is a value - it is the result of some computation which
> has not yet been assigned to a variable. This is perhaps more obvious with
> an operator: "1 + 2" is not a variable, it is the value 3; internally, a
> temporary variable is probably used to hold that value, but that temporary
> variable is never accessible to the programmer. If you have function
> add($a, $b) { return $a + $b; }, then add(1,2) is still not a variable in
> any meaningful sense.


Value is vague term. I would like to use "expression". Expression is
anything that has value.
Variables/constants are values that have actual storage.
Literals are values that may not have actual storage.

Joe pointed out PHP treats temporary variable differently. I suppose
temporary variable is created
for values not used as usual variable. e.g. Function return value.

It may be the thing we need to reconsider.
Temporary variable is an variable after all. It may be used in context that
is changed then discarded.

Even if we raise errors for temporary variables, it's better to raise
_the_same_error_ where is it allowed.

<?php
define('MYERROR', -1);
function &f1() {return -1;}  // `E_NOTICE` rather than `E_STRICT` 
function &f2() {return MYERROR;} // `E_NOTICE` rather than `E_STRICT` 

$v = f1();
$v = 2;
var_dump($v);

$v = f2();
$v = 2;
var_dump($v);
?>
http://3v4l.org/9LdkK#v551

I understand that return by ref and returning literal/constant is
contradictional, yet
it seems too much care for developers. Developer may simply return value
that
indicates some error in return by ref function should be allowed w/o error.
IMHO.



>  It's better to keep basic rule. IMHO.
> > […]
>
> `array_pop()` is a stack-manipulation function, so the latter is the correct
> use, with $v going on to be used as the rest of the stack. If you're using
> it for something other than stack manipulation, neither is correct, because
> it's the wrong choice of function.


User may use `array_slice()` for it, but `array_pop()` is intuitive what it
does and works
perfectly except unneeded error. Therefore,  user surprises what is the
"Only variable
references should be ..." means.

Anyway, I wrote a blog about this spec many years ago and the entry is
accessed
constantly even today.  I suppose PHP7 will have more intuitive/flexible
parsing for
complex expressions(e.g. f()[2]->method(), etc, isn't it?), then this spec
may confuse
more users.

We don't need unwanted side effects, therefore this change should be done
carefully.
I wouldn't argue with this. If removing "Only variable references should be
..." error is
feasible, I would like to propose this change.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

Next page: https://externals.io/message/79412.md?page=2
