I've updated the RFC to include details on adding isset/unset as well as references, detailed below:
isset/unset:
class TimePeriod {
private $Seconds = 3600;
public $Hours {
get { return $this->Seconds / 3600; }
set { $this->Seconds = $value; }
isset { return !is_null($this->Seconds); }
unset { $this->Seconds = NULL; }
}
}
References:
class SampleClass {
private $_dataArray = array(1,2,5,3);
public $dataArray {
&get { return &$this->_dataArray; }
}
}
$o = new SampleClass();
sort($o->dataArray);
/* $o->dataArray == array(1,2,3,5); */
Comments?
These would also include automatic implementations which call the respective functions on the backing field. I could see only allowing isset/unset automatic implementations if get/set were also specified as automatic implementations.
Default implementations of isset/unset
I'm also fielding comments/ideas on a way to always provide automatic implementations of isset/unset for any accessor that didn't define one automatically. One idea was for the isset (unspecified implementation) which would return true if the getter provided any value which evaluated to true, such as this:
class TimePeriod {
private $Seconds = 3600;
public $Hours {
get { return $this->Seconds / 3600; }
set { $this->Seconds = $value; }
}
}
/* Default Implementation Concept */
isset { return (int)$this->Hours; }
unset { $this->Hours = NULL; }
Note that the automatic implementation of unset is not strictly the same as an unset() but without any sort of unset implementation a call to unset() would do nothing. Alternatively we could throw an error to a call on isset and/or unset against a property which didn't define an implementation.
Thoughts?
-Clint
Clint,
Very nice job overall! Looking quite good.
Alternatively we could throw an error to a call on isset and/or unset against a property which didn't define an implementation.
I don't care for that concept much. All it's doing is trading one set
of boilerplate for another. I'd prefer the get() !== null approach,
since there is a zval allocated for it, so the isset() part.
And I do like the unset overloading, which is right inline with __unset()...
Additionally, is something like this possible?
class Foo {
private $bar = 1;
public $bar {
get { return $this->bar; }
set { $this->bar = (int) $value; }
}
}
The reason that I ask, is that's kind of what's done with __get() and
__set() right now, the magic is called when it's out of scope. So in
this case, we can have a public variable with the same name as the
private one, but with validations attached to the public exposure...
Just a thought...
Anthony
I've updated the RFC to include details on adding isset/unset as well as references, detailed below:
isset/unset:
class TimePeriod {
private $Seconds = 3600;public $Hours {
get { return $this->Seconds / 3600; }
set { $this->Seconds = $value; }
isset { return !is_null($this->Seconds); }
unset { $this->Seconds = NULL; }
}
}References:
class SampleClass {
private $_dataArray = array(1,2,5,3);
public $dataArray {
&get { return &$this->_dataArray; }
}
}
$o = new SampleClass();
sort($o->dataArray);
/* $o->dataArray == array(1,2,3,5); */
Comments?
These would also include automatic implementations which call the respective functions on the backing field. I could see only allowing isset/unset automatic implementations if get/set were also specified as automatic implementations.
Default implementations of isset/unset
I'm also fielding comments/ideas on a way to always provide automatic implementations of isset/unset for any accessor that didn't define one automatically. One idea was for the isset (unspecified implementation) which would return true if the getter provided any value which evaluated to true, such as this:
class TimePeriod {
private $Seconds = 3600;public $Hours {
get { return $this->Seconds / 3600; }
set { $this->Seconds = $value; }
}
}
/* Default Implementation Concept */isset { return (int)$this->Hours; }
unset { $this->Hours = NULL; }Note that the automatic implementation of unset is not strictly the same as an unset() but without any sort of unset implementation a call to unset() would do nothing. Alternatively we could throw an error to a call on isset and/or unset against a property which didn't define an implementation.
Thoughts?
-Clint
Hi!
would it be possible to add a second shorthand syntax to the complete
automatic implementation?
Examples:
class TimePeriod
{
public $Hours {};
public property $Hours;
public $Hours {property};
}
That could save quite some typing.
Overall, i really like it.
On Tue, Apr 24, 2012 at 2:56 PM, Anthony Ferrara ircmaxell@gmail.comwrote:
Clint,
Very nice job overall! Looking quite good.
Alternatively we could throw an error to a call on isset and/or unset
against a property which didn't define an implementation.I don't care for that concept much. All it's doing is trading one set
of boilerplate for another. I'd prefer the get() !== null approach,
since there is a zval allocated for it, so the isset() part.And I do like the unset overloading, which is right inline with
__unset()...Additionally, is something like this possible?
class Foo {
private $bar = 1;
public $bar {
get { return $this->bar; }
set { $this->bar = (int) $value; }
}
}The reason that I ask, is that's kind of what's done with __get() and
__set() right now, the magic is called when it's out of scope. So in
this case, we can have a public variable with the same name as the
private one, but with validations attached to the public exposure...Just a thought...
Anthony
On Tue, Apr 24, 2012 at 8:31 AM, Clint M Priest cpriest@zerocue.com
wrote:I've updated the RFC to include details on adding isset/unset as well as
references, detailed below:isset/unset:
class TimePeriod {
private $Seconds = 3600;public $Hours {
get { return $this->Seconds / 3600; }
set { $this->Seconds = $value; }
isset { return !is_null($this->Seconds); }
unset { $this->Seconds = NULL; }
}
}References:
class SampleClass {
private $_dataArray = array(1,2,5,3);
public $dataArray {
&get { return &$this->_dataArray; }
}
}
$o = new SampleClass();
sort($o->dataArray);
/* $o->dataArray == array(1,2,3,5); */
Comments?
These would also include automatic implementations which call the
respective functions on the backing field. I could see only allowing
isset/unset automatic implementations if get/set were also specified as
automatic implementations.Default implementations of isset/unset
I'm also fielding comments/ideas on a way to always provide automatic
implementations of isset/unset for any accessor that didn't define one
automatically. One idea was for the isset (unspecified implementation)
which would return true if the getter provided any value which evaluated to
true, such as this:class TimePeriod {
private $Seconds = 3600;public $Hours {
get { return $this->Seconds / 3600; }
set { $this->Seconds = $value; }
}
}
/* Default Implementation Concept */isset { return (int)$this->Hours; } unset { $this->Hours = NULL; }
Note that the automatic implementation of unset is not strictly the same
as an unset() but without any sort of unset implementation a call to
unset() would do nothing. Alternatively we could throw an error to a call
on isset and/or unset against a property which didn't define an
implementation.Thoughts?
-Clint
Hi!
would it be possible to add a second shorthand syntax to the complete
automatic implementation?Examples:
class TimePeriod
{
public $Hours {};
public property $Hours;
public $Hours {property};
}
How it is different from just public $Hours and why one would need this?
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Here is a copy of what Dennis had written to me regarding automatic implementations from C# (the model):
Originally, C# did not support automatically implemented properties.
There are several reasons why they were added. The first reason, is that while the syntax for properties is the same as the syntax for member variables, there is still some subtle differences in behaviour that cannot be accounted for by properties. Here are some examples:
- Variables may be used as input to out/ref arguments. Properties may not.
- Properties may throw exceptions - variables will never do that.
- Properties may have side effects or take a really long time to execute.
Variables have no side effects and will always be as fast as can be expected for the given type.- Properties support different accessibility - variables do not
- When using reflection the properties and fields are treated as different MemberTypes so are located differently (GetFields vs GetProperties for
example)
Some of these above example still apply (reflection, execution time), so the automatic implementations may simply be there as a way for authors to indicate their intention to make them execute code at a later time.
This suggestion below shortens the syntax even further.
-----Original Message-----
From: Stas Malyshev [mailto:smalyshev@sugarcrm.com]
Sent: Tuesday, April 24, 2012 12:11 PM
To: Benjamin Eberlei
Cc: internals@lists.php.net
Subject: Re: [PHP-DEV] RFC: Property get/set syntax (added isset/unset and references)
Hi!
would it be possible to add a second shorthand syntax to the complete
automatic implementation?Examples:
class TimePeriod
{
public $Hours {};
public property $Hours;
public $Hours {property};
}
How it is different from just public $Hours and why one would need this?
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi!
- Variables may be used as input to out/ref arguments. Properties
may not.
This will probably be true for properties too, in some cases. However,
it is in no way an advantage.
- Properties may throw exceptions - variables will never do that.
In PHP, properties can not throw exceptions unless your code does, and
variable access can throw exceptions too if you do that in __get.
- Properties may have side effects or take a really long time to
execute. Variables have no side effects and will always be as fast
as can be expected for the given type.
Again, depends on __get.
- Properties support different accessibility - variables do not
In PHP, variables have access modifiers.
- When using reflection the properties and fields are treated as
different MemberTypes so are located differently (GetFields vs
GetProperties for
example)
It may be so, but I don't see where there's an advantage.
So, none of these explain why would one want to create "default
implementation" property. Could you explain?
Some of these above example still apply (reflection, execution time),
so the automatic implementations may simply be there as a way for
authors to indicate their intention to make them execute code at a
later time.
If they would want to make them execute code at a later time, they could
convert them to properties then. I think the whole point of introducing
properties is that they would work transparently for the client, so if
we saying we'd have to pre-define them as properties that defeats the
whole purpose of it. I think as proposed "default implementation" only
makes it more confusing as it works differently from user-space
implementations.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Clint,
Additionally, one more comment related to the read-only and
write-only. I noticed that you're using E_ERROR
for improper access.
Obviously you don't want this to be a warning, as the execution
shouldn't continue because that would be undefined. However, what
about setting it to E_RECOVERABLE_ERROR, so that it can be captured
and recovered from...? The engine wouldn't be in an unstable state,
so if we install an error_handler that throws an exception, there's no
reason to force-terminate the application...
I guess I'm just adverse to using E_ERROR
except for cases where it's
literally not safe to continue (usually because the engine is put in
an inconsistent state)...
Anthony
I've updated the RFC to include details on adding isset/unset as well as references, detailed below:
isset/unset:
class TimePeriod {
private $Seconds = 3600;public $Hours {
get { return $this->Seconds / 3600; }
set { $this->Seconds = $value; }
isset { return !is_null($this->Seconds); }
unset { $this->Seconds = NULL; }
}
}References:
class SampleClass {
private $_dataArray = array(1,2,5,3);
public $dataArray {
&get { return &$this->_dataArray; }
}
}
$o = new SampleClass();
sort($o->dataArray);
/* $o->dataArray == array(1,2,3,5); */
Comments?
These would also include automatic implementations which call the respective functions on the backing field. I could see only allowing isset/unset automatic implementations if get/set were also specified as automatic implementations.
Default implementations of isset/unset
I'm also fielding comments/ideas on a way to always provide automatic implementations of isset/unset for any accessor that didn't define one automatically. One idea was for the isset (unspecified implementation) which would return true if the getter provided any value which evaluated to true, such as this:
class TimePeriod {
private $Seconds = 3600;public $Hours {
get { return $this->Seconds / 3600; }
set { $this->Seconds = $value; }
}
}
/* Default Implementation Concept */isset { return (int)$this->Hours; }
unset { $this->Hours = NULL; }Note that the automatic implementation of unset is not strictly the same as an unset() but without any sort of unset implementation a call to unset() would do nothing. Alternatively we could throw an error to a call on isset and/or unset against a property which didn't define an implementation.
Thoughts?
-Clint
That makes sense to me, a number (possibly all) of the errors I've added/modified could be eligible for this. In those cases it would do "the next best thing," such as ignore a setter definition, etc. I may not have a perfect understanding of what would leave the "engine in an unstable state however" as Derick mentions on his post about E_RECOVERABLE_ERROR.
-----Original Message-----
From: Anthony Ferrara [mailto:ircmaxell@gmail.com]
Sent: Tuesday, April 24, 2012 10:40 AM
To: Clint Priest
Cc: internals@lists.php.net
Subject: Re: [PHP-DEV] RFC: Property get/set syntax (added isset/unset and references)Clint,
Additionally, one more comment related to the read-only and write-only. I noticed that you're using
E_ERROR
for improper access.
Obviously you don't want this to be a warning, as the execution shouldn't continue because that would be undefined. However, what
about setting it to E_RECOVERABLE_ERROR, so that it can be captured and recovered from...? The engine wouldn't be in an unstable
state, so if we install an error_handler that throws an exception, there's no reason to force-terminate the application...I guess I'm just adverse to using
E_ERROR
except for cases where it's literally not safe to continue (usually because the engine is put in
an inconsistent state)...Anthony
I've updated the RFC to include details on adding isset/unset as well as references, detailed below:
isset/unset:
class TimePeriod {
private $Seconds = 3600;public $Hours {
get { return $this->Seconds / 3600; }
set { $this->Seconds = $value; }
isset { return !is_null($this->Seconds); }
unset { $this->Seconds = NULL; }
}
}References:
class SampleClass {
private $_dataArray = array(1,2,5,3);
public $dataArray {
&get { return &$this->_dataArray; }
}
}
$o = new SampleClass();
sort($o->dataArray);
/* $o->dataArray == array(1,2,3,5); */
Comments?
These would also include automatic implementations which call the respective functions on the backing field. I could see only
allowing isset/unset automatic implementations if get/set were also specified as automatic implementations.Default implementations of isset/unset
I'm also fielding comments/ideas on a way to always provide automatic implementations of isset/unset for any accessor that didn't
define one automatically. One idea was for the isset (unspecified implementation) which would return true if the getter provided any
value which evaluated to true, such as this:class TimePeriod {
private $Seconds = 3600;public $Hours {
get { return $this->Seconds / 3600; }
set { $this->Seconds = $value; }
}
}
/* Default Implementation Concept */isset { return (int)$this->Hours; }
unset { $this->Hours = NULL; }Note that the automatic implementation of unset is not strictly the same as an unset() but without any sort of unset implementation
a call to unset() would do nothing. Alternatively we could throw an error to a call on isset and/or unset against a property which didn't
define an implementation.Thoughts?
-Clint
Hi!
public $dataArray {
&get { return &$this->_dataArray; }
This is not correct. Please read:
http://php.net/manual/en/language.references.return.php
These would also include automatic implementations which call the
respective functions on the backing field. I could see only allowing
isset/unset automatic implementations if get/set were also specified
as automatic implementations.
Could you please explain what is the use of automatic implementations?
I.e., why won't you just have a variable?
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi!
These would also include automatic implementations which call the
respective functions on the backing field. I could see only allowing
isset/unset automatic implementations if get/set were also specified
as automatic implementations.
Another thing about that. The "automatic implementation" creates
variable starting with __. When exactly this happens - if all bodies are
not defined? Any of the bodies are not defined? What if I implement
interface like this:
interface iSampleInterface {
public $MyProperty {
get;
set;
}
}
Does this produce automatic __MyProperty or not?
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
I will double-check (that it doesn't) but it should not per the spec, in the case of an interface this is not an automatic implementation but instead a 'must-have' declaration, which could later become an automatic implementation when defined within a class which implements that interface.
-----Original Message-----
From: Stas Malyshev [mailto:smalyshev@sugarcrm.com]
Sent: Tuesday, April 24, 2012 12:34 PM
To: Clint Priest
Cc: internals@lists.php.net
Subject: Re: [PHP-DEV] RFC: Property get/set syntax (added isset/unset and references)
Hi!
These would also include automatic implementations which call the
respective functions on the backing field. I could see only allowing
isset/unset automatic implementations if get/set were also specified
as automatic implementations.
Another thing about that. The "automatic implementation" creates variable starting with __. When exactly this happens - if all bodies are not defined? Any of the bodies are not defined? What if I implement interface like this:
interface iSampleInterface {
public $MyProperty {
get;
set;
}
}
Does this produce automatic __MyProperty or not?
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227