I Want Scalar Objects in PHP

Matt Sparks on July 18, 2018

Originally Posted on DevelopmentMatt.com Recently, I read an interesting article from Andrew Carter entitled Make PHP Great Again [cheap plug: t... [Read Full]
markdown guide
 

"PHP 8 is a great opportunity to cleanup these inconsistencies."

This alone would be reason enough, lol

 

i'd like better and consistent treatment for callables
examples of what we can not do ATM:

array_map(class::method, $array);
//
$o = new stdClass;
$o->f = function($s) {echo "Hello $s";};
$o->f("dev.to");
PHP Warning:  Uncaught Error: Call to undefined method stdClass::f() in php shell code:1

also

  • Closure as constants
  • method toArray for SplTypes : Queue, DoublyLinkedList, etc
  • a Map datatype that is not the actual array
  • a way to programmaticaly define class constants in __construct (for int types)
  • a way to hide class properties from being listed by get_object_vars or a a method that dont list privates.

Just what's in my head ATM :)

 

In the example you give with the callable, it would create conflict between properties and methods of classes, that are totally separated in PHP.
This will create backward compatibility problems.

 

There would be a conflict only if no policy is set up.
What seems obvious to me is to check for declared methods first.
Like you cannot "create" a class identifier that has already being declared in class.
There's already a check to prevent from using an name that is declared "private" for example.
That's the "identity" of the class.
Then if someone declares a property with same name a warning should be raised (or another error policy) because after all good practices : that doesnt' make sense to have a property named as an action or a method named as a noun.

So a simple check to put in place when invoking a class member, priority :

  • first class methods if it exists
  • then check property existence AND that is a callable

This avoids overwriting declared methods while giving the possibility to construct methods dynamically or just use callable as a valid value for a property without aliasing it prior to being able to use it.
Callable as a type must be supported in every part of the language.

Note that example show an anonymous function but it can be any object with magic "__invoke" that is supposedly a valid type for an property.
Valid type but not fully handled ATM.

and for another suggestion since i found a way to declared constant dynamically:
a way to get constants declared in a specific namespace.
something like:

// returns an array with name => value (as get_defined_constants does)
get_namespace_constants(__NAMESPACE__);

Agree with you on those points. An update can be done on this features.
And of course, it would make sense as you say, because of Closure as a type and __invoke method :)
+1 !

 
<?php

class Name {
    private $name;

    function __construct($name) {
        $this->name = $name;
    }

    function length() {
        return mb_strlen($this->name, 'UTF-8');
    }

    /* object replace() */
    function ooReplace($needle, $replace) {
        $this->name = str_replace($needle, $replace, $this->name);
        return $this->name;
    }

    /* functional replace() */
    function replace($needle, $replace) {
        return str_replace($needle, $replace, $this->name);
    }

    function __toString() {
        return $this->name;
    }
}

$name = new Name("žluťásek");
var_dump((string) $name);                 // string(11) "žluťásek"
var_dump($name->length());                // int(8)
var_dump($name->replace('ťáse', 'ční'));  // string(10) "žlučník"
var_dump((string) $name);                 // string(11) "žluťásek"
 
 

well, i personally dont care, php as not strictly typed language curently is not ready for this. imho.
ps: in last snippet you have syntax error. :P :)

 

php as not strictly typed language curently is not ready for this.

Mind expanding your point here? What does type safety has to do with scalar objects?

 

I mean, when type is not enforced, scalar object can have different methods depending on current type. Or am I wrong?

Maybe I'm missing something, but isn't how JavaScript does it with .reduce, .map, .split etc... practically what the suggested improvement wants? And JS doesn't enforce types either, right?

Yep, and it would just require an extra step sometimes to explicitly cast to the desired type. We have to do this in PHP/JS sometimes now as it is.

It could be usable tho... i imagine this:

$array = ((string) $float)->explode(.);
 

But we are slowly heading in that direction, far too slowly really. Strict types help you code better and stop of lot of issues that can take time to debug.

PHP 7 made some headway here with strict_types, if you don't want it don't set it to true, or just leave out your type hints altogether - very sloppy!

Personaly I'd love to have fixed types for variables:

int $myInt = 1;
string $myString = "1234";
bool $myBool = 45;  // Fails 
int $myInt2 = "5678";  // Fails

Or even better without the annoying $ prefix which does nothing IMHO:

int myInt = 1;
string myString = "1234";
bool myBool = 45;  // Fails
int myInt2 = "5678";  // Fails
 

Yes, all those Ruby and Smalltalk developers are producing completely unusable garbage because they lack manifest typing. /s

I like PHP's dynamic loose scripting nature. If you want that more verbose kind of thing, there is Java, or Swift, or whatever.

PHP's current nature fulfills a unique niche in my toolkit and I like it the way it is (although I'm all for consistent naming and moving to a more dynamic OO style).

 

Are you proposing this work similar to Java with auto boxing? I mean something like

$var = 'hella clever string here';
$var->someStringMethodHere();

Is cool and all, but are we going to assume auto boxing here or are we going with no more primitives at all? I feel if we still want real primitives(which I assume we do), something like

$var = new String('Even more hella clever string here');
$var->someStringMethodHere();

is a better approach than automatically auto boxing all scalars into objects. That way we have both scalar objects and primitives still.

Perhaps instead even better could be having the 'scalar object' not be a real object at all, but instead the access before in the first example I provided instead be a bit of syntactic sugar for

someStringMethodHere('hella clever string here');

Something like that would be great. Without generics and such I don't think we really want them to be objects cause we wouldn't want something like

function foo(stdClass $obj) : void {
 echo $obj::class;
}
$var = 'scalar string';
foo($var);

Because then there's literally no point to using stdClass as a type hint since everything would be one.

Also I just want a real god damn array. None of this map masquerading as an array bullshit. Sometimes I just need some integers one after the other in memory and not have to worry about if someone used a string as an index by accident.

 

This was already proposed,implemented and rejected a few years ago:

github.com/rossriley/php-scalar-ob...

Looks like now it exists as a PHP extension:

github.com/nikic/scalar_objects

 

But this would be so much better if it was part of the core and had properly published methods.

PHP needs to grow and keep up with the needs of developers rather than developers continuously getting frustrated with the lack modernity in one of the most popular languages in use. If PHP does not embrace good OOP practices it will loose it's popularity. Given that .NET Core has been available cross platform for some time now, it is becoming a popular draw for those of us who long for something better. If it were not for a host of projects and a large code base I would have moved on already.

Time will tell and for me time is running out with the arcane state PHP is still in, despite the major leap in PHP 7 it's still very old fashioned.

 

I agree with you 100%, If it wasn't for the large code bases I have to maintain every single day, I would be using .Net Core, but hey, I think the killer feature here would be generics. That is really needed.

 
var_dump($hello.replace('Matt', 'Bob')); // Hello Bob!

Using the dot notation only for these scalar objects would be horrible IMO. Better stick with the -> operator.

Quick edit: I realized that maybe just a typo on your part lol.

 
 

It'd be a huge step in making PHP much more OOP. After Generics, I think its the most important feature to be added to 8.

 

Wow, I never thought generics would be needed/discussed in PHP, like, ever. Thanks for pointing out! :)

 

When using loosely typed programming languages for very large code bases you end up wishing for namespacing and strict types to enforce isolation and contracts between code modules at the language level. Once you have strict types you quickly figure out you need generics to fully type-check all your code. Once you have generics you realize you can have strictly typed generic collection classes and Maybe types (e.g. java's optional). Once you use those you realize that they'd be awesome if they had fluent API's so you could do collection->map(...)->filter(...)->sort(...)->reduce(...), and so all those collection classes and maybe types are extended to support that style (e.g. java's streams). And then when you're writing that kind of code, it would be awfully handy to have pattern matching and macro-like meta-syntax (see: scala).

And that is how all programming languages used for large projects, including PHP, are on a path to become like haskell, scala, etc. which already have all of these features. It is inevitable.

 

The ability to set type_strict globally for a project. Either via php.ini, composer.json or version used 8.y.z-strict || 8.y.z

I feel like the more type strictness / checking PHP gets the more it is viewed as a professional language (I know, it s BS but it is what I see in around the web).

Function argument order is another one that needs correcting.

 

With every PHP release I keep hoping that the mess will be cleaned up ... Let's hope PHP 8 does something drastic.

 

The one and only answer to the original tweet I believe is to remove the dollar sign '$' it's hideous

 

I don't hate the dollar sign per say but I agree it is pretty glaring. But I mean putting a different symbol or the word var or something in front of all the variables wouldn't be much better either. I'm curious about another idea you have for it though!

 
 
 

I have been working on a library for this exact thing. Check it out: twine.phlak.net

 
 

Are you volunteering to do the work, or are would you be willing to sponsor someone (at market rates) to work on it?

code of conduct - report abuse