On Wed, Apr 20, 2016 at 11:05 PM, guilhermeblanco@gmail.com <
guilhermeblanco@gmail.com> wrote:
Dmitry is even involved in the discussion of having IS_UNDEF until
constructor ends, then enforcing type hinting at the end of constructor to
trigger potential invalid instance state. It created a mess in the internal
structure by creating a 3-state value: uninitialized, absent of value
(null) and assigned value. All this problem would be solved by merging null
into accepted value.
So far the proposed solution there to take a wrong assumption to assume a
default value based on type defined (like int = 0, string = '', etc), which
are all potential valid values, leading to unpredictable behavior if a
develop misses to assign a value to that property.
Sure, people will say that now PHP will require a NullPointerException,
PHP is turning into Java, or that I don't know what I'm talking about
because they coded for Amiga and I don't (yes, I've seen that already in
this mailing list). But the fact is that keeping control of 3-state flags
are hard to maintain.
I think this is not to make PHP like Java, and it totally makes sense -
Nullable should be a type of a type instead of a state. In Haskell it's
named Maybe or Option, and It's better than NullPointerException.
Here is a discussion from Haskell community:
https://mail.haskell.org/pipermail/haskell-cafe/2011-April/091269.html
--
Best Regards,
Yo-An Lin
I think this is not to make PHP like Java, and it totally makes sense -
Nullable should be a type of a type instead of a state. In Haskell it's
named Maybe or Option, and It's better than NullPointerException.Here is a discussion from Haskell community:
https://mail.haskell.org/pipermail/haskell-cafe/2011-April/091269.html
Why is it /better/?
final class None {}
final class Some {
public $value;
public function __construct($value) {
$this->value = $value;
}
}
final class Maybe {
private static $none;
private $value;
private function __construct($value) {
$this->value = $value;
}
public static function NOTHING() {
if (self::$nothing === null) {
self::$nothing = new Nothing();
}
return new static(self::$nothing);
}
public static function SOME($value) {
return new static(new Some($value));
}
public function hasSome(): bool {
return $this->value !== static::$none;
}
public function isNone(): bool {
return $this->value === static::$none;
}
public function unwrap() {
if ($this->value === static::$none) {
trigger_error('NullPointerException', E_USER_ERROR);
}
return $this->value->value;
}
}
// ----------------------------------------
function f1(): Option {}
$x = f1();
if ($x->hasSome()) {
echo $x->unwrap(); // 42
}
$x = f1();
if ($x->isNone()) {
echo -1;
}
echo f1()->unwrap(); // error: NullPointerException :P
// ----------------------------------------
function f2(): ?int {}
$y = f2();
if (isset($y)) {
echo $y; // 42
}
$y = f2();
if ($y === null) {
echo -1;
}
echo f2(); // null
You can easily build your own Option or Maybe and add the additional
bookkeeping to your runtime but it will not make your program more
secure or anything. It just adds more method calls and makes it more
verbose.
You can already use static code analyzers to detect if null is being
ignored in your code, however, right now they mainly have to rely on
PhpDoc that is often not properly documented. Adding an explicit syntax
to PHP for documentation would make PhpDoc obsolete and allow static
code analyzers to perform their job better and PHP to error out during
runtime if something else is being returned.
Honestly, null is not our problem. Every language has its null, just
because they wrap it or rename it does not make null suddenly vanish
from the universe. :P
--
Richard "Fleshgrinder" Fussenegger
I think this is not to make PHP like Java, and it totally makes sense -
Nullable should be a type of a type instead of a state. In Haskell it's
named Maybe or Option, and It's better than NullPointerException.Here is a discussion from Haskell community:
https://mail.haskell.org/pipermail/haskell-cafe/2011-April/091269.htmlWhy is it /better/?
final class None {}
final class Some {
public $value; public function __construct($value) { $this->value = $value; }
}
final class Maybe {
private static $none; private $value; private function __construct($value) { $this->value = $value; } public static function NOTHING() { if (self::$nothing === null) { self::$nothing = new Nothing(); } return new static(self::$nothing); } public static function SOME($value) { return new static(new Some($value)); } public function hasSome(): bool { return $this->value !== static::$none; } public function isNone(): bool { return $this->value === static::$none; } public function unwrap() { if ($this->value === static::$none) { trigger_error('NullPointerException', E_USER_ERROR); } return $this->value->value; }
}
// ----------------------------------------
function f1(): Option {}
$x = f1();
if ($x->hasSome()) {
echo $x->unwrap(); // 42
}$x = f1();
if ($x->isNone()) {
echo -1;
}echo f1()->unwrap(); // error: NullPointerException :P
// ----------------------------------------
function f2(): ?int {}
$y = f2();
if (isset($y)) {
echo $y; // 42
}$y = f2();
if ($y === null) {
echo -1;
}echo f2(); // null
You can easily build your own Option or Maybe and add the additional
bookkeeping to your runtime but it will not make your program more
secure or anything. It just adds more method calls and makes it more
verbose.You can already use static code analyzers to detect if null is being
ignored in your code, however, right now they mainly have to rely on
PhpDoc that is often not properly documented. Adding an explicit syntax
to PHP for documentation would make PhpDoc obsolete and allow static
code analyzers to perform their job better and PHP to error out during
runtime if something else is being returned.Honestly, null is not our problem. Every language has its null, just
because they wrap it or rename it does not make null suddenly vanish
from the universe. :P--
Richard "Fleshgrinder" Fussenegger
IMHO, the point of Optional types is the intention, if you get an
Option<Foo> from a method, you have to deal with a None branch. Of course
you can just unwrap and go on, but it's a developer decision to do that,
not an oversight as using a Foo|null (or ?Foo) as an object directly.
IMHO, the point of Optional types is the intention, if you get an
Option<Foo> from a method, you have to deal with a None branch. Of course
you can just unwrap and go on, but it's a developer decision to do that,
not an oversight as using a Foo|null (or ?Foo) as an object directly.
IMOH, the point of ?T is the intention, if you get a null from a method,
you have to deal with a null branch. Of course you can just ignore it
and go on, but it's a developer decision to do that, not an oversight as
using a Option<T> as an object directly.
Sorry, but this works in both directions. The problem is not null, the
problem is that there is no system that warns you (e.g. a compiler)
about the missing null check. I think that Ceylon solved this problem
extremely nicely without the introduction of something special.
function fn(): ?T {}
$x = fn();
if (is $x T) {}
else {}
Not doing as above is a compiler error in Ceylon. However, I already
wrote multiple times that there are already statical code analysis tools
available that can find exactly such things in your code. One just needs
to use them.
--
Richard "Fleshgrinder" Fussenegger
Hi Richard,
IMHO, the point of Optional types is the intention, if you get an
Option<Foo> from a method, you have to deal with a None branch. Of course
you can just unwrap and go on, but it's a developer decision to do that,
not an oversight as using a Foo|null (or ?Foo) as an object directly.IMOH, the point of ?T is the intention, if you get a null from a method,
you have to deal with a null branch. Of course you can just ignore it
and go on, but it's a developer decision to do that, not an oversight as
using a Option<T> as an object directly.Sorry, but this works in both directions. The problem is not null, the
problem is that there is no system that warns you (e.g. a compiler)
about the missing null check. I think that Ceylon solved this problem
extremely nicely without the introduction of something special.
Of course, this works in both directions, but I see a value in Option types:
function getByEmail(string $email) : ?User {}
$user = getByEmail("foo@bar.com");
echo $user->getName();
I neglect the nullable return but works at first , all fine...
.. a week later... "Warning: Call to a member function getName() on null"
With Option type:
function getByEmail(string $email) : Option[User] {}
$user = getByEmail("foo@bar.com");
echo $user->getName();
IDE could warn me and It crashes right away, an option type must be
unwrapped so I get the "intention" immediately :)
function fn(): ?T {}
$x = fn();
if (is $x T) {}
else {}Not doing as above is a compiler error in Ceylon. However, I already
wrote multiple times that there are already statical code analysis tools
available that can find exactly such things in your code. One just needs
to use them.
That's really nice
--
Richard "Fleshgrinder" Fussenegger
Option types are nice, but I feel we are going a bit off-topic. Option
types work better with other niceties like for comprehensions, pattern
matching... And I don't see PHP going that route in the near future, and
probably It's not okay for PHP to go that route...
Nullable return types is a better fit for PHP, null has been in the
language from the beginning, I agree here
Hi Richard,
IMHO, the point of Optional types is the intention, if you get an
Option<Foo> from a method, you have to deal with a None branch. Of course
you can just unwrap and go on, but it's a developer decision to do that,
not an oversight as using a Foo|null (or ?Foo) as an object directly.IMOH, the point of ?T is the intention, if you get a null from a method,
you have to deal with a null branch. Of course you can just ignore it
and go on, but it's a developer decision to do that, not an oversight as
using a Option<T> as an object directly.Sorry, but this works in both directions. The problem is not null, the
problem is that there is no system that warns you (e.g. a compiler)
about the missing null check. I think that Ceylon solved this problem
extremely nicely without the introduction of something special.Of course, this works in both directions, but I see a value in Option types:
function getByEmail(string $email) : ?User {}
$user = getByEmail("foo@bar.com");
echo $user->getName();I neglect the nullable return but works at first , all fine...
.. a week later... "Warning: Call to a member function getName() on null"With Option type:
function getByEmail(string $email) : Option[User] {}
$user = getByEmail("foo@bar.com");
echo $user->getName();IDE could warn me and It crashes right away, an option type must be
unwrapped so I get the "intention" immediately :)function fn(): ?T {}
$x = fn();
if (is $x T) {}
else {}Not doing as above is a compiler error in Ceylon. However, I already
wrote multiple times that there are already statical code analysis tools
available that can find exactly such things in your code. One just needs
to use them.That's really nice
--
Richard "Fleshgrinder" FusseneggerOption types are nice, but I feel we are going a bit off-topic. Option
types work better with other niceties like for comprehensions, pattern
matching... And I don't see PHP going that route in the near future, and
probably It's not okay for PHP to go that route...Nullable return types is a better fit for PHP, null has been in the
language from the beginning, I agree here
Option is no better than a union type with null[1]. If a language
requires an option to be unwrapped then it can do the same with some
type or null. This is what Swift does. These things are exactly
equivalent.
However in PHP we do not have generics, which means a nullable type is
actually better because we can express the type that participates with
null. With an Option type we cannot.
[1] At least with the behaviors here. If Option is a Traverable that
returns 0 or 1 items then we can use that behavior to our advantage.
Of course, we lose the ability to express the underlying option type.
Hi Richard,
On Sat, Apr 23, 2016 at 2:30 PM, Fleshgrinder php@fleshgrinder.com
wrote:IMHO, the point of Optional types is the intention, if you get an
Option<Foo> from a method, you have to deal with a None branch. Of
course
you can just unwrap and go on, but it's a developer decision to do
that,
not an oversight as using a Foo|null (or ?Foo) as an object directly.IMOH, the point of ?T is the intention, if you get a null from a method,
you have to deal with a null branch. Of course you can just ignore it
and go on, but it's a developer decision to do that, not an oversight as
using a Option<T> as an object directly.Sorry, but this works in both directions. The problem is not null, the
problem is that there is no system that warns you (e.g. a compiler)
about the missing null check. I think that Ceylon solved this problem
extremely nicely without the introduction of something special.Of course, this works in both directions, but I see a value in Option
types:function getByEmail(string $email) : ?User {}
$user = getByEmail("foo@bar.com");
echo $user->getName();I neglect the nullable return but works at first , all fine...
.. a week later... "Warning: Call to a member function getName() on null"With Option type:
function getByEmail(string $email) : Option[User] {}
$user = getByEmail("foo@bar.com");
echo $user->getName();IDE could warn me and It crashes right away, an option type must be
unwrapped so I get the "intention" immediately :)function fn(): ?T {}
$x = fn();
if (is $x T) {}
else {}Not doing as above is a compiler error in Ceylon. However, I already
wrote multiple times that there are already statical code analysis tools
available that can find exactly such things in your code. One just needs
to use them.That's really nice
--
Richard "Fleshgrinder" FusseneggerOption types are nice, but I feel we are going a bit off-topic. Option
types work better with other niceties like for comprehensions, pattern
matching... And I don't see PHP going that route in the near future, and
probably It's not okay for PHP to go that route...Nullable return types is a better fit for PHP, null has been in the
language from the beginning, I agree hereOption is no better than a union type with null[1]. If a language
requires an option to be unwrapped then it can do the same with some
type or null. This is what Swift does. These things are exactly
equivalent.
My point was about the developer receiving an Optional type, being less
error-prone than a nullable type. Not a language advantage.
However in PHP we do not have generics, which means a nullable type is
actually better because we can express the type that participates with
null. With an Option type we cannot.
Yes, I was talking generically here, Option Types without generics-like
behaviour are a lot less useful
Nullable return types is indeed a better fit for PHP as I said
[1] At least with the behaviors here. If Option is a Traverable that
returns 0 or 1 items then we can use that behavior to our advantage.
Of course, we lose the ability to express the underlying option type.
Option is no better than a union type with null[1]. If a language
requires an option to be unwrapped then it can do the same with some
type or null. This is what Swift does. These things are exactly
equivalent.
I don't think that's strictly true. Option<T> (or Maybe<T>) types that must
be unwrapped can usually be safely nested as Option<Option<...>>. This is
important if you have a generic class Foo<T> that uses Option<T> internally
and Foo is instantiated as Foo<Option<string>> (using string as an
example), causing an Option<Option<string>> to occur inside Foo. If
Option<string> meant string|null, the Option<Option<string>> would become
string|null|null and the real "null" at runtime would become ambiguous.
Nonetheless, nesting is very rarely needed, but it is something to keep in
mind when using generics in combination with union with null for
nullability.
However in PHP we do not have generics, which means a nullable type is
actually better because we can express the type that participates with
null. With an Option type we cannot.[1] At least with the behaviors here. If Option is a Traverable that
returns 0 or 1 items then we can use that behavior to our advantage.
Of course, we lose the ability to express the underlying option type.