Hello internals,
Java supports the "final" keyword before a variable to determines that this 
variables never change it reference. If I declare a variable as "final", I 
can only initialize that once, then I could not change it after (but I can 
manipulate the instance, without issues).
There some special reason to PHP doesn't supports things like that?
final $number = 123; 
$number = 456; // Error: you change change final variables.
final $object = new stdClass; 
$object->allowed = true; // No error.
This feature make sense because it tells to dev that the variable value 
could not be updated directly (new reference). Which make easy to identify 
when a variable is modifiable or not.
It is valid for a RFC?
- It can uses the "final" keyword;
 - It doesn't a BC;
 
I too think that a final variable can be useful to make some internal 
improvements on language (but it could be a BC for PHP internals). I mean, 
as the variable could not be modified, then it don't need be a "flexible" 
type internally (I guess that it is a zval, right?).
Reference: https://github.com/kalessil/phpinspectionsea/issues/363
-- 
David Rodrigues
Hi David
2017-06-28 18:10 GMT+02:00 David Rodrigues david.proweb@gmail.com:
Hello internals,
Java supports the "final" keyword before a variable to determines that this
variables never change it reference. If I declare a variable as "final", I
can only initialize that once, then I could not change it after (but I can
manipulate the instance, without issues).There some special reason to PHP doesn't supports things like that?
It seems like what you are looking for here is actually a constant[1]. 
However constants do not support non scalar types, such as array or 
objects, what would really solve it on the objects side of things 
would be the introduction of a "readonly" keyword or similar, like 
that of C#[2]
final $number = 123;
$number = 456; // Error: you change change final variables.final $object = new stdClass;
$object->allowed = true; // No error.This feature make sense because it tells to dev that the variable value
could not be updated directly (new reference). Which make easy to identify
when a variable is modifiable or not.It is valid for a RFC?
- It can uses the "final" keyword;
 - It doesn't a BC;
 
Anything is usually valid for an RFC, however I think (personally) 
that this should rather be an RFC for a readonly keyword if anything
I too think that a final variable can be useful to make some internal
improvements on language (but it could be a BC for PHP internals). I mean,
as the variable could not be modified, then it don't need be a "flexible"
type internally (I guess that it is a zval, right?).Reference: https://github.com/kalessil/phpinspectionsea/issues/363
--
David Rodrigues
[1] http://php.net/constants 
[2] https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/readonly
-- 
regards,
Kalle Sommer Nielsen 
kalle@php.net
2017-06-28 18:59 GMT+02:00 Kalle Sommer Nielsen kalle@php.net:
Hi David
2017-06-28 18:10 GMT+02:00 David Rodrigues david.proweb@gmail.com:
Hello internals,
Java supports the "final" keyword before a variable to determines that
this
variables never change it reference. If I declare a variable as "final",
I
can only initialize that once, then I could not change it after (but I
can
manipulate the instance, without issues).There some special reason to PHP doesn't supports things like that?
It seems like what you are looking for here is actually a constant[1].
However constants do not support non scalar types, such as array or
objects,
Arrays are supported, but not objects.
Regards, Niklas
what would really solve it on the objects side of things
would be the introduction of a "readonly" keyword or similar, like
that of C#[2]final $number = 123;
$number = 456; // Error: you change change final variables.final $object = new stdClass;
$object->allowed = true; // No error.This feature make sense because it tells to dev that the variable value
could not be updated directly (new reference). Which make easy to
identify
when a variable is modifiable or not.It is valid for a RFC?
- It can uses the "final" keyword;
 - It doesn't a BC;
 Anything is usually valid for an RFC, however I think (personally)
that this should rather be an RFC for a readonly keyword if anythingI too think that a final variable can be useful to make some internal
improvements on language (but it could be a BC for PHP internals). I
mean,
as the variable could not be modified, then it don't need be a "flexible"
type internally (I guess that it is a zval, right?).Reference: https://github.com/kalessil/phpinspectionsea/issues/363
--
David Rodrigues[1] http://php.net/constants
[2] https://docs.microsoft.com/en-us/dotnet/csharp/language-
reference/keywords/readonly--
regards,Kalle Sommer Nielsen
kalle@php.net
2017-06-28 19:37 GMT+02:00 Niklas Keller me@kelunik.com:
Arrays are supported, but not objects.
Ah yes ofcourse, my apologies.
-- 
regards,
Kalle Sommer Nielsen 
kalle@php.net
2017-06-28 13:59 GMT-03:00 Kalle Sommer Nielsen kalle@php.net:
Hi David
It seems like what you are looking for here is actually a constant[1].
However constants do not support non scalar types, such as array or
objects, what would really solve it on the objects side of things
would be the introduction of a "readonly" keyword or similar, like
that of C#[2]
Not on reality. :(
The "final" keyworks make a "local scope" variable value "blocked to 
rewrite" after instantiate it. 
Okay, it sounds like a "const", and it is, but "not as we known it".
While constants are class member (or globals), a final variable is just a 
variable blocked to rewrite, and it could be initialized with a new data 
content every time that the context is called (eg. a function).
For instance (note that the parameter is "final", then I can't modify the 
parameter variable, but it can receives a new value each time that I call 
this function):
function write(final $message) { echo $message; } 
write("Hello"); 
write("World"); 
// Write "Hello World" on ouput.
Or then:
function randomNumber() { 
final $number = mt_rand(); 
echo $number;
// $number = mt_rand_again(); // <-- will not be allowed! 
} 
randomNumber(); 
 // Write "0.123" 
randomNumber(); 
 // Write "0.456" 
[1] http://php.net/constants
[2] https://docs.microsoft.com/en-us/dotnet/csharp/language-
reference/keywords/readonly
-- 
David Rodrigues
 
Walter Parker walterp@gmail.com 
 wrote:
Constant may not have been the right word (or idea), but I agree with
Kalle. We should use readonly as the keyword here and not final as the
keyword. We can keep the same scoping rules so the following would work:
> function randomNumber() {
>
*readonly *$number =mt_rand();
I agree that "readonly" is a better keyword, but we have to points here:
- "final" is used on some language (Java, C++ I guess);
 - "final" keyword does exists on PHP with a "similar" behaviour;
 
If we can implements "readonly" is good too, because turn it more implicit.
2017-06-28 15:46 GMT-03:00 David Rodrigues david.proweb@gmail.com:
2017-06-28 13:59 GMT-03:00 Kalle Sommer Nielsen kalle@php.net:
Hi David
It seems like what you are looking for here is actually a constant[1].
However constants do not support non scalar types, such as array or
objects, what would really solve it on the objects side of things
would be the introduction of a "readonly" keyword or similar, like
that of C#[2]
Not on reality. :(
The "final" keyworks make a "local scope" variable value "blocked to
rewrite" after instantiate it.
Okay, it sounds like a "const", and it is, but "not as we known it".While constants are class member (or globals), a final variable is just a
variable blocked to rewrite, and it could be initialized with a new data
content every time that the context is called (eg. a function).For instance (note that the parameter is "final", then I can't modify the
parameter variable, but it can receives a new value each time that I call
this function):function write(final $message) { echo $message; }
write("Hello");
write("World");
// Write "Hello World" on ouput.Or then:
function randomNumber() {
final $number =mt_rand();
echo $number;// $number = mt_rand_again(); // <-- will not be allowed!
}
randomNumber();
 // Write "0.123"
randomNumber();
 // Write "0.456"
[1] http://php.net/constants
[2] https://docs.microsoft.com/en-us/dotnet/csharp/language-refe
rence/keywords/readonly--
David Rodrigues
-- 
David Rodrigues
2017-06-29 1:07 GMT+02:00 David Rodrigues david.proweb@gmail.com:
readonly $number =
mt_rand();
I agree that "readonly" is a better keyword, but we have to points here:
- "final" is used on some language (Java, C++ I guess);
 - "final" keyword does exists on PHP with a "similar" behaviour;
 
If we can implements "readonly" is good too, because turn it more implicit.
True we could re-use the final keyword, but think about it this way,
we got final methods and final classes which means it cannot be
overridden/extended respectively, if the final keyword then would also
apply to variables but it would mean they could not be written to,
that would create a WTF-factor.
The readonly keyword would work for any visibility modifiers, so 
inherited classes or extending classes may read a protected property, 
but not modify it as well:
class A { 
protected readonly $b;
public function __construct() { 
$this->b = 'C'; 
} 
}
class B extends A { 
public function read() { 
echo $this->b; 
}
public function write() { 
$this->b = 'D'; 
} 
}
$b = new B;
$b->read(); // "C" 
$b->write(); // <- error
-- 
regards,
Kalle Sommer Nielsen 
kalle@php.net
The final modifier would likely clash with property type definitions, if 
those ever make it to the language.
Still, a few pain-points remain:
- References to properties (you cannot reference final properties anymore, 
and that is effectively a BC break for anything using reflection and
closure scope binding) - Arrays and resources as properties
 - Named (Factory) constructors
 - Property nullability - how do you define if a property was written to 
the "last valid time" before freezing it - Unset properties and providing an alternative mechanism to distinguish 
"uninitiated", "undefined" and "frozen" in he event of final properties
usage, without breaking current property access semantics 
This is the exact same set of problems we had with the typed properties 
RFC, and which caused the RFC to fail: please take all these in 
consideration while designing the feature.
2017-06-29 1:07 GMT+02:00 David Rodrigues david.proweb@gmail.com:
readonly $number =
mt_rand();
I agree that "readonly" is a better keyword, but we have to points here:
- "final" is used on some language (Java, C++ I guess);
 - "final" keyword does exists on PHP with a "similar" behaviour;
 If we can implements "readonly" is good too, because turn it more
implicit.
True we could re-use the final keyword, but think about it this way,
we got final methods and final classes which means it cannot be
overridden/extended respectively, if the final keyword then would also
apply to variables but it would mean they could not be written to,
that would create a WTF-factor.The readonly keyword would work for any visibility modifiers, so
inherited classes or extending classes may read a protected property,
but not modify it as well:class A {
protected readonly $b;public function __construct() {
$this->b = 'C';
}
}class B extends A {
public function read() {
echo $this->b;
}public function write() {
$this->b = 'D';
}
}$b = new B;
$b->read(); // "C"
$b->write(); // <- error--
regards,Kalle Sommer Nielsen
kalle@php.net
References to properties ...is effectively a BC break for anything
using reflection and closure scope binding
No it's not.
If that feature was brought into PHP, any code that is currently 
valid, that the library is capable of reflecting, would still be valid 
code, that the library would still be capable of reflecting.
Yes, there would be some new syntax which the library wouldn't be 
aware of, which wouldn't be supported in the library, but that is not 
a BC break.
Adding new syntax to a language does mean that people who have 
libraries that inspect code based on the current syntax would need to 
choose between:
- 
Updating the library to support the new syntax, or asking for a PR for that.
 - 
Saying that the library can inspect code up to the version before
the new syntax was introduced, but doesn't support later code. 
I can see that would be annoying for the authors of those libraries, 
as they would obviously prefer to not have to make that choice, but it 
isn't a BC break.
snip - lots of difficult to solve technical problems
This is the exact same set of problems we had with the typed properties
RFC, and which caused the RFC to fail: please take all these in
consideration while designing the feature.
Yup. I think any discussion without at least some kind of plan for 
dealing with the technical problems for implementing this isn't likely 
to be productive.
cheers 
Dan
Hey Dan,
On Thu, Jun 29, 2017 at 12:07 PM, Dan Ackroyd danack@basereality.com 
wrote:
References to properties ...is effectively a BC break for anything
using reflection and closure scope bindingNo it's not.
If that feature was brought into PHP, any code that is currently
valid, that the library is capable of reflecting, would still be valid
code, that the library would still be capable of reflecting.
We discussed this before: any library designed around the capability of 
dealing with a generic object would break in these scenarios, which is why 
I always bring it up. It needs to be considered in an RFC, including 
possible mitigation and alternatives.
Marco Pivetta
Hi
2017-06-28 20:46 GMT+02:00 David Rodrigues david.proweb@gmail.com:
The "final" keyworks make a "local scope" variable value "blocked to
rewrite" after instantiate it.
Okay, it sounds like a "const", and it is, but "not as we known it".
I get that, but I still don't understand why you would forcefully need 
it to be a variable still then if you know the value is gonna be 
constant, of course besides global visibility or in iterations
-- 
regards,
Kalle Sommer Nielsen 
kalle@php.net
Am 29.06.2017 um 04:50 schrieb Kalle Sommer Nielsen:
2017-06-28 20:46 GMT+02:00 David Rodrigues david.proweb@gmail.com:
The "final" keyworks make a "local scope" variable value "blocked to
rewrite" after instantiate it.
Okay, it sounds like a "const", and it is, but "not as we known it".I get that, but I still don't understand why you would forcefully need
it to be a variable still then if you know the value is gonna be
constant, of course besides global visibility or in iterations
because constants are expensive in PHP when "define()" is a function 
call and "const" is very limited for no good reason
"no good reason" because if it really would be compile time the 
following won't work and so why can't you use 'const' within a 
if-statement when you in fact can CONCAT two with define() set constant 
which are part of a if-statement themself
if(PHP_SAPI !== 'cli') 
{ 
define('MY_PHP_SELF', $_SERVER['SCRIPT_NAME']); 
define('rh_serverurl', PROTOCOL_PREFIX . MY_SERVER_NAME . $rh_port); 
} 
else 
{ 
define('MY_PHP_SELF', '/' . basename($_SERVER['SCRIPT_NAME'])); 
define('rh_serverurl', 'http://localhost'); 
} 
const rh_phpself = rh_serverurl . MY_PHP_SELF;
Final is about having immutable data. Immutable doesn't mean that it's a 
system wide constant, it means that it's referentially pure in its scope.
Am 29.06.2017 um 04:50 schrieb Kalle Sommer Nielsen:
2017-06-28 20:46 GMT+02:00 David Rodrigues david.proweb@gmail.com:
The "final" keyworks make a "local scope" variable value "blocked to
rewrite" after instantiate it.
Okay, it sounds like a "const", and it is, but "not as we known it".I get that, but I still don't understand why you would forcefully need
it to be a variable still then if you know the value is gonna be
constant, of course besides global visibility or in iterationsbecause constants are expensive in PHP when "define()" is a function call
and "const" is very limited for no good reason"no good reason" because if it really would be compile time the following
won't work and so why can't you use 'const' within a if-statement when you
in fact can CONCAT two withdefine()set constant which are part of a
if-statement themself
if(PHP_SAPI !== 'cli')
{
define('MY_PHP_SELF', $_SERVER['SCRIPT_NAME']);
define('rh_serverurl', PROTOCOL_PREFIX . MY_SERVER_NAME . $rh_port);
}
else
{
define('MY_PHP_SELF', '/' . basename($_SERVER['SCRIPT_NAME']));
define('rh_serverurl', 'http://localhost');
}
const rh_phpself = rh_serverurl . MY_PHP_SELF;
Am 29.06.2017 um 11:08 schrieb Marco Pivetta:
Final is about having immutable data. Immutable doesn't mean that it's a
system wide constant, it means that it's referentially pure in its scope.
i refered to "why you would forcefully need it to be a variable still 
then if you know the value is gonna be constant" and as long constants 
in PHP are a) very expensive and b) "const" pretends to be compile time 
which is provable wrong with my sample code are terrible to use
in other languages like Visual Basic constants are fast, in PHP they are 
slow, both in define and access
On 29 Jun 2017 11:05 AM, "lists@rhsoft.net mailto:lists@rhsoft.net"
<lists@rhsoft.net mailto:lists@rhsoft.net> wrote:Am 29.06.2017 um 04:50 schrieb Kalle Sommer Nielsen: 2017-06-28 20:46 GMT+02:00 David Rodrigues <david.proweb@gmail.com <mailto:david.proweb@gmail.com>>: The "final" keyworks make a "local scope" variable value "blocked to rewrite" after instantiate it. Okay, it sounds like a "const", and it is, but "not as we known it". I get that, but I still don't understand why you would forcefully need it to be a variable still then if you know the value is gonna be constant, of course besides global visibility or in iterations because constants are expensive in PHP when "define()" is a function call and "const" is very limited for no good reason "no good reason" because if it really would be compile time the following won't work and so why can't you use 'const' within a if-statement when you in fact can CONCAT two with `define()` set constant which are part of a if-statement themself ____________________________________________________ if(PHP_SAPI !== 'cli') { define('MY_PHP_SELF', $_SERVER['SCRIPT_NAME']); define('rh_serverurl', PROTOCOL_PREFIX . MY_SERVER_NAME . $rh_port); } else { define('MY_PHP_SELF', '/' . basename($_SERVER['SCRIPT_NAME'])); define('rh_serverurl', 'http://localhost'); } const rh_phpself = rh_serverurl . MY_PHP_SELF;
in other languages like Visual Basic constants are fast, in PHP they are
slow, both in define and access
Two things here:
- don't ever consider visual basic for any comparison of any sort: it's 
basically (ha!) the worst example of a programming language that I can
think of before malborge - speed is not relevant in this scope: program correctness is. Final 
properties would allow switching value object representations from accessor
(getter) based logic (extremely slow) to public property based (less
overhead, also in writing). 
Marco Pivetta
Am 29.06.2017 um 11:25 schrieb Marco Pivetta:
On Thu, Jun 29, 2017 at 11:19 AM, lists@rhsoft.net
mailto:lists@rhsoft.net <lists@rhsoft.net mailto:lists@rhsoft.net>
wrote:in other languages like Visual Basic constants are fast, in PHP they are slow, both in define and accessTwo things here:
- don't ever consider visual basic for any comparison of any sort:
 
it's basically (ha!) the worst example of a programming language that I
can think of before malborge
stop it - many people say the same about PHP
- speed is not relevant in this scope: program correctness is. Final
 
properties would allow switching value object representations from
accessor (getter) based logic (extremely slow) to public property based
(less overhead, also in writing)
in which scope is speed not relevant?
depends on your application, in my scopes i try to avoid expensive 
opcodes and useless function calls, program correctness is a completly 
different thing and it's not one or the other but both
I will try answer the questions:
I get that, but I still don't understand why you would forcefully need
it to be a variable still then if you know the value is gonna be
constant, of course besides global visibility or in iterations
"final" is not "const". "final" mean a initial state that will never be 
modified, but it could be initialized with different values on same 
runtime. It is like I say "my name is David and will be all the time David 
when I am on an informal context" and "my name is Rodrigues and will be all 
the time Rodrigues when I am on a forma context", on same "document". 
https://pastebin.com/QCrmrZQe
True we could re-use the final keyword, but think about it this way,
we got final methods and final classes which means it cannot be
overridden/extended respectively, if the final keyword then would also
apply to variables but it would mean they could not be written to,
that would create a WTF-factor.
It is done on Java, for instance. We can use "final" on classes or 
functions that mean that it cannot be overrided, or "final" in variables, 
that mean that it cannot be re-referenced (rewrite after initialization). 
And not seems strange to me. We could "abstract the term" to understand 
that in any of cases (for classes, function or variables) the information 
could not be overrided after defined.
The readonly keyword would work for any visibility modifiers, so
inherited classes or extending classes may read a protected property,
but not modify it as well:
For me, the readonly keyword should be implemented on future to another 
case: make a public property writeable only by the own class. But it is for 
another discussion.
The
finalmodifier would likely clash with property type definitions,
if those ever make it to the language.
Still, a few pain-points remain:
- References to properties (you cannot reference final properties
 
anymore, and that is effectively a BC break for anything using reflection
and closure scope binding)
I don't know if I understand, but for properties you could redefine a final 
property on constructor (as Java). https://pastebin.com/bTZcUT33
- Arrays and resources as properties
 
You can modify arrays or resources on final variables, since that you don't 
modify the reference. https://pastebin.com/D38wL8x7
- Named (Factory) constructors
 
I don't understand.
- Property nullability - how do you define if a property was written to
 
the "last valid time" before freezing it
Because PHP don't have support to "variable initialization" (eg. "$name;") 
then you should only initializate it when you will write the initial (and 
freezed) value. https://pastebin.com/Ua6DFUC1
- Unset properties and providing an alternative mechanism to distinguish
 
"uninitiated", "undefined" and "frozen" in he event of final properties
usage, without breaking current property access semantics
It will be modified. Final variables still are a variable, but with the 
status that "never change after initializate" (a flag). We can just 
implement a new reflection method to properties to identify if it 
isFinal(), or even for variables like "is_final($var)". By other side, this 
last doesn't make sense because the final variable is just a "code 
documentation" to the own dev knows that is not allowed modify it anymore. 
Maybe we need implements that only for ReflectionProperty (first case), 
because it could be part of a code that the user have not modify access 
(eg. vendor code). https://pastebin.com/jSjNQACd
2017-06-29 6:25 GMT-03:00 Marco Pivetta ocramius@gmail.com:
On Thu, Jun 29, 2017 at 11:19 AM, lists@rhsoft.net lists@rhsoft.net
wrote:in other languages like Visual Basic constants are fast, in PHP they are
slow, both in define and accessTwo things here:
- don't ever consider visual basic for any comparison of any sort: it's
 
basically (ha!) the worst example of a programming language that I can
think of before malborge- speed is not relevant in this scope: program correctness is. Final
 
properties would allow switching value object representations from accessor
(getter) based logic (extremely slow) to public property based (less
overhead, also in writing).Marco Pivetta
-- 
David Rodrigues
Hi David,
On Thu, Jun 29, 2017 at 11:58 AM, David Rodrigues david.proweb@gmail.com 
wrote:
The
finalmodifier would likely clash with property type definitions,
if those ever make it to the language.
Still, a few pain-points remain:
- References to properties (you cannot reference final properties
 
anymore, and that is effectively a BC break for anything using reflection
and closure scope binding)I don't know if I understand, but for properties you could redefine a
final property on constructor (as Java). https://pastebin.com/bTZcUT33
No, the problem is following:
class Foo { final public $bar = 'baz'; }
$foo = new Foo;
$bar = & $foo->bar;
$bar = 'taz';
var_dump($foo->bar);
This kind of ugly code will break.
- Arrays and resources as properties
 You can modify arrays or resources on final variables, since that you
don't modify the reference. https://pastebin.com/D38wL8x7
That doesn't make it "final", although I get your point, and yes, it 
basically prevents decreasing the reference count on that particular 
property. I think this kills the usefulness of the feature, but it's indeed 
still useful.
- Named (Factory) constructors
 I don't understand.
Relatively common pattern:
class Foo { 
private final $bar; 
private function __construct() { /* hammertime */ } 
public static function create($something) : self { 
$instance = new self(); 
$instance->bar = $something; 
return $instance; 
} 
}
See also http://verraes.net/2014/06/named-constructors-in-php/
- Property nullability - how do you define if a property was written to
 
the "last valid time" before freezing itBecause PHP don't have support to "variable initialization" (eg. "$name;")
then you should only initializate it when you will write the initial (and
freezed) value. https://pastebin.com/Ua6DFUC1
Got it, so a "first write" would be equivalent to a freeze operation? When 
do you seal the property if the value isn't overwritten? Would you disable 
default values for properties that are declared final?
- Unset properties and providing an alternative mechanism to
 
distinguish "uninitiated", "undefined" and "frozen" in he event of final
properties usage, without breaking current property access semanticsIt will be modified. Final variables still are a variable, but with the
status that "never change after initializate" (a flag). We can just
implement a new reflection method to properties to identify if it
isFinal(), or even for variables like "is_final($var)". By other side, this
last doesn't make sense because the final variable is just a "code
documentation" to the own dev knows that is not allowed modify it anymore.
Maybe we need implements that only for ReflectionProperty (first case),
because it could be part of a code that the user have not modify access
(eg. vendor code). https://pastebin.com/jSjNQACd
The reflection API is a given, but the problem is still the same:
class Foo { 
private final $foo; 
private $lazyLoad; 
public function saySomething() { 
return 'Saying ' . $this->foo; 
} 
private function __construct() { 
} 
public static function new() : self { 
$instance = new self(); 
$instance->foo = 'something'; 
return $instance; 
} 
public static function newLazy() : self { 
$instance = new self(); 
$instance->lazyLoad = function () use ($instance) { 
$instance->foo = 'something lazy'; 
}; 
unset($instance->foo); 
return $instance; 
} 
public function __get($name) { 
($this->lazyLoad)(); 
return $this->foo; 
} 
}
$foo = Foo::new(); 
var_dump($foo->saySomething()); 
$lazyFoo = Foo::newLazy(); 
var_dump($lazyFoo->saySomething());
Hope that clarifies it.
Marco Pivetta