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.
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.
Any comments?
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi all,
I think we can get rid of this error now when literal is returned.
The reason we haveE_STRICT
error is that legacy PHP didn't
support this, I suppose.
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/
From: Andrea Faulds [mailto:ajf@ajf.me], Thursday, December 04, 2014 9:33 AM
Hi all,
I think we can get rid of this error now when literal is returned.
The reason we haveE_STRICT
error is that legacy PHP didn't
support this, I suppose.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...
Hi Andrea,
I think we can get rid of this error now when literal is returned.
The reason we haveE_STRICT
error is that legacy PHP didn't
support this, I suppose.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.
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
Hi all,
I think we can get rid of this error now when literal is returned.
The reason we haveE_STRICT
error is that legacy PHP didn't
support this, I suppose.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.Any comments?
I made a little better sample code.
I would like to hear opinions from engine experts.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi all,
Sorry for multiple posts. This would be the last one.
I think we can get rid of this error now when literal is returned.
The reason we haveE_STRICT
error is that legacy PHP didn't
support this, I suppose.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.Any comments?
I made a little better sample code.
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
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/
Hi Andrea, Stas and all
<?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.
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
Raising errors for this kind of code is not good. IMHO.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
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.
Hi Levi,
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 afterstream_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
Hi Yasuo,
Hi all,
Sorry for multiple posts. This would be the last one.
I think we can get rid of this error now when literal is returned.
The reason we haveE_STRICT
error is that legacy PHP didn't
support this, I suppose.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.Any comments?
I made a little better sample code.
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
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
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
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.
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/
Hi Kalle,
Thank you for the list. It's very helpful!
2014-12-04 9:28 GMT+01:00 Yasuo Ohgaki yohgaki@ohgaki.net:
Any comments?
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.netI 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 ifcurrent()
and family is, and this is not, it will make it inconsistent)
rsort()
shuffle()
sort()
usort()
uasort()
uksort()
Agreed.
I would like to do like
$var;
array_walk(func(), function ($v, $k) use ($var) {
$var .= $v.$k;
});
though.
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 ascurrent()
next()
-- Same ascurrent()
prev()
-- Same ascurrent()
I think
array_pop()
array_splice()
extract()
These could be changed.
First of all, removing warnings only for these is feasible in PHP7?
We need Engine experts. Thank you.
Does anyone object to remove warnings for these?
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi all,
I think we can get rid of this error now when literal is returned.
The reason we haveE_STRICT
error is that legacy PHP didn't
support this, I suppose.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.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());
?>
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()));
?>
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());
?>
Any comments?
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi all,
On Thu, Dec 4, 2014 at 5:28 PM, Yasuo Ohgaki yohgaki@ohgaki.net
wrote:I think we can get rid of this error now when literal is returned.
The reason we haveE_STRICT
error is that legacy PHP didn't
support this, I suppose.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.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());
?>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]
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
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
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
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
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
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.
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]
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]
Hi Rowan,
On Sat, Dec 6, 2014 at 11:25 PM, Rowan Collins rowan.collins@gmail.com
wrote:
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.
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.
$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.
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
Hi!
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.
The C world already has terminology for this:
-
lvalues - values on the left-hand side of an assignment, they can be assigned to
Examples in PHP include:
- $foo
- $foo->bar
- $foo->bar[0]
-
rvalues - a superset of lvalues, these are values that can be on the right-hand side of an assignment
Examples include:
- All the lvalues above
- 3
- 2 + 3
- foobar()
- $foo + $bar
- (int)$foo
In C, you (usually) can only get pointers to lvalues, as only lvalues can be written to. In PHP, it would make sense only to be able to reference lvalues, as only lvalues can be written to. In fact, we (almost?) always treat references as if they were assignments, hence why you can reference non-existent variables, because you can assign to non-existent variables. AFAIK this may be because referencing a value inherently modifies it (in PHP 5 and earlier, it sets the if_ref flag, while in PHP 7 it changes it to an IS_REFERENCE type). Even if referencing a value didn’t modify it, it allows you to do so later.
Doing something like &(2+3) makes no sense as (2 + 3) isn’t a variable, it’s a temporary rvalue that is only used once.
As others have said, there is no use-case for allowing assignments to or references to rvalues, it’s completely nonsensical. What would make sense is adding things like array_top() or array_bottom(), and perhaps allowing NULL
rvalues to be passed to by-reference parameters with defaults.
Thanks!
Andrea Faulds
http://ajf.me/
Hi Rowan,
On Sat, Dec 6, 2014 at 11:25 PM, Rowan Collins
rowan.collins@gmail.com
wrote: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.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 thanE_STRICT
function &f2() {return MYERROR;} //E_NOTICE
rather thanE_STRICT
$v = f1();
$v = 2;
var_dump($v);$v = f2();
$v = 2;
var_dump($v);
?>
http://3v4l.org/9LdkK#v551I 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.
$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.User may use
array_slice()
for it, butarray_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.
You keep talking about these "errors" being a burden on the programmer, but accepting that in principle it would be better to avoid such situations, so I want to reiterate: these are Strict Standards hints - they tell the programmer "we're not going to stop you doing this, but you might want to find a better way to write it". This seems like a perfect balance to me.
You keep talking about these "errors" being a burden on the programmer, but accepting that in principle it would be better to avoid such situations, so I want to reiterate: these are Strict Standards hints - they tell the programmer "we're not going to stop you doing this, but you might want to find a better way to write it". This seems like a perfect balance to me.
This is one of those 'warnings' that inevitably appear in the legacy
code and invariably the quick fix is to introduce the variable just to
shut it up. It is not the right way of doing it, but unravelling why it
was used in the first place can be time consuming. One of those things
on the to do list to document better and then go back through and see if
things can be improved. It IS the lack of better documentation on how to
do things correctly which is the real problem here. Where traditionally
an 'object' was an array of multidimensional data which WAS passed
around by reference and that has now be wrapped in a class to modernise
it. In many cases we simply don't need an array of objects, simply an
array of references to the data which can be passed by reference to a
'class' of static code is the easiest and fastest way of processing
material for web pages. We don't need to create magic get and set
routines for every element of the data, a simple array read is ALL that
is needed?
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk