Req #73608 [Opn]: inconstistent const behavior
| From: | spam2 at rhsoft dot net | Date: | Tue, 13 Dec 2016 23:47:22 +0000 |
| Subject: | Req #73608 [Opn]: inconstistent const behavior | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-205971@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=73608&edit=1
ID: 73608
User updated by: spam2 at rhsoft dot net
Reported by: spam2 at rhsoft dot net
Summary: inconstistent const behavior
Status: Open
Type: Feature/Change Request
Package: Scripting Engine problem
PHP Version: 7.0.13
Block user comment: N
Private report: N
New Comment:
how does that change the fact that in case of "if($x == 1)" you have no idea at compile
time if $x will be 1 - either my sample would be invalid code and needs to be a
fatal/compile/whatever error or you can use const with variables
the point is the damned function call for define() which means 15 define() calls are 0.2% runtime of
our complete core-application while you can assign thounsands of variables in the same runtime but
well, they are variables which can be changed and are not visible in every scope without additional
opcodes $GLOBALS or global $foo;
Previous Comments:
------------------------------------------------------------------------
[2016-12-13 23:19:49] dave at mudsite dot com
Yes I did see your example, and tried to expand upon it highlighting the use of runtime.
To specifically address your (desired) example:
<?php
$x = 1;
if($x == 1)
{
const CONST_A = 'A';
}
We must read this to say that we wish to define a constant based on a variable expression. During
compilation the compiler does not know what the value of any compiled-variable is, rather it knows
how to look for the value during execution. So understanding that we can look at the if statement
and see that we compare the equality of compiled-variable($x) and a constant(1). Only during
execution will the result of that equality be known.
Taking your example to the next logical example to showcase why it's not possible we have:
<?php
$x = 2;
if ($x == 1) {
const CONST_A = 'A';
} else {
const CONST_A = 'AAA';
}
Knowing that const is a compile-time portion of the grammar, how can we properly compile this
example? We can't very well set a constant to two values, nor can we know which constant to
compile. This is why "because it's compile time" is not a lie.
Enter define(). As you show in your example it's the proper way to update the constant-table
during runtime when variable-expressions can be evaluated to know which branch of code will be
executed.
<?php
$x = 2;
if ($x == 1) {
define('CONST_A', 'A');
} else {
define('CONST_A', 'AAA');
}
------------------------------------------------------------------------
[2016-12-13 16:17:40] spam2 at rhsoft dot net
did you look at my example?
const CONST_B = 'TEST ' . CONST_A; *works* here and since one part (CONST_A) of it is
inside a if-statement how can that be when "a constant can not be variable"
------------------------------------------------------------------------
[2016-12-13 15:10:25] dave at mudsite dot com
"because it's compile time" does not appear to exactly be a lie. The const keyword
wants to be used (as is declared in the grammar) as a top-level statement. Why? Well a constant is
compiled as a left, or right, node to op-codes at compile time, and therefore needs to be a literal
constant. Now, imagine this code:
<?php
class Foo {
function __toString() {
return "I'm a FOO";
}
}
$f = new Foo();
const CONST_A = $f;
const CONST_B = 'TEST ' . CONST_A;
echo CONST_B . "\n";
?>
You would get a compilation fatal here as well, since a constant can not be a variable. define()
however, is a runtime function that can accept variables and update the constant table with a
reference to that compiled-variable(here that's an object). So looking again at your example,
you're using the const-keyword within a statement dependent on a variable, therefore the value
of a constant expression is variable, and a constant can not be variable. So if you want to define
a constant that is variable, you have use of define() to do it at runtime.
That said, just moving the grammar for T_CONST from top_statement into statement does get your code
to run; however, I imagine the desire to keep const's out of places dependent on variables is
the languages desire. Any internals people could feel free to correct my thoughts here.
------------------------------------------------------------------------
[2016-11-25 23:51:54] spam2 at rhsoft dot net
Description:
------------
why can't you still not use 'const' inside a if-statement?
"because it's compile time" is a lie which is easily to realize because otherwise
CONST_B could never contain the value of CONST_A which was defined in the if-statement before
[harry@srv-rhsoft:/downloads]$ cat test.php
<?php
$x = 1;
if($x == 1)
{
define('CONST_A', 'A');
}
const CONST_B = 'TEST ' . CONST_A;
echo CONST_B . "\n";
?>
[harry@srv-rhsoft:/downloads]$ php test.php
TEST A
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=73608&edit=1