[PHP-DEV] Re: Basic Type Alias

2024-01-24 Thread Oladoyinbo Vincent
I have been so busy lately, which gave me no time to work on the type alias
implementation. but I will be happy if anyone can volunteer/help in
implementing this feature so that it can be introduced in PHP 8.4 or 9.0,
as this will help optimise a lot of people and codebase out there.


On Monday, October 30, 2023, Larry Garfield  wrote:

> On Sun, Oct 29, 2023, at 9:52 PM, Jorg Sowa wrote:
> > I really like the idea and I would love to see it in PHP. I'm wondering
> > however, what would be the scope of the feature and how complex would be
> > designed type system. Examples I saw in this thread could be easily
> > replaced with union and intersection types (i.e. numeric as int|float).
> In
> > my opinion, there is a little benefit implementing in this shape making
> the
> > PHP core more complex.
> >
> > The two use cases of user defined types in PHP which would benefit a lot
> > IMO, would be:
> > 1. Typed arrays similar to Typescript.
> > 2. Semantic types which would increase the security of systems. Example:
> > type UserId = int;
> >
> > function setUserId_1(int $userId){}
> >
> > function setUserId_2(UserId $userId){}
> >
> > setUserId_1(5); // OK
> > setUserId_2(5); // TypeError
> >
> > setUserId_1(UserId(5)); // OK
> > setUserId_2(UserId(5)); // OK
> >
> > Kind regards,
> > Jorg
>
> Simple unions are the easiest to talk about in quick examples, but the
> real benefit of type aliases is in other cases, some of which they would
> enable.
>
> Example:
>
> I have a real parameter defined in my attributes library like this:
>
> \ReflectionProperty|\ReflectionMethod|\ReflectionClassConstant $subject
>
> And it appears several times, I believe.  That would definitely be nicer
> if simplified to an alias.
>
> Example:
>
> There's general consensus that callable types would be beneficial:
> callable(RequestInterface, string): string or similar.  But inline, that
> gets long and complicated fast.  Type aliases would allow simplifying that
> to
>
> type callable(RequestInterface, string): string as PropertyRetriever
>
> function foo(PropertyRetriever $c) { ... }
>
> Example:
>
> As in the above example, type aliases serve as documentation for callables
> or complex types, explaining what that complex ruleset actually means,
> semantically.
>
> Example:
>
> If generics or typed arrays ever happen, they'd probably be useful here,
> too.
>
> Note that using type aliases in a required-fashion is a different matter,
> and potentially not feasible.  Free standing variables are untyped, which
> means setUserId(UserId $id) could not require a UserId, because there's no
> way to define a variable as being a UserId, not an int.  While I can
> definitely see a value in that kind of restriction, in practice I don't
> think PHP is capable of it without vastly larger changes.
>
> --Larry Garfield
>


-- 
Best Regards,
O. Vincent


[PHP-DEV] [Discussion] Variable Type Declaration Before Usage

2023-11-05 Thread Oladoyinbo Vincent
Hello Internals,

I was wondering if php could introduce this feature or if any experienced C
dev here can work on the implementation of this feature.

Local based variable declaration before usage is available in most
languages like javascript, python, and many more. php has this, but it's
only available while working/dealing with oop related.

There is already an RFC on this:
https://wiki.php.net/rfc/local_variable_types, but it doesn't propose a
good usage syntax to promote readability.

Well, i figured out how this feature syntax could look like:

```

$info: string;
$price: float;
$number: int = 125;
$run: \Closure = fn( string $str ) => $str;

echo $number; // 125

$info = $number; // TypeError
$price = $number; // TypeError
$number = 12.5; // TypeError
$run = "hello world"; // TypeError
```

I was kind of thinking if the declared variables may also affect functions
params:

```php

function priceInfo($price, $info)
{
return $info . ': $ ' . $price;
}


echo priceInfo(12, 2); // TypeError

echo priceInfo(12.5, 'Price:'); // Price: $12.5

```


So, what is your opinion on this?

Best Regards,
Oladoyinbo Vincent.


[PHP-DEV] Short Function Syntax

2023-11-02 Thread Oladoyinbo Vincent
Hello Internals,

I don't know maybe this discussion has been raised before, but i feel we
should re-discuss this.

`function` syntax is kinda verbose for naming methods in class, let's take
a look at the below example:


```php

class Greet {

public function __construct(
private string $name,
private string $city
) {}

private function init(): string
{
return "Hello {$this->name}, From {$this->city}";
}
}

```

I know that the `fn` Syntax is already used for arrow functions, but what i
am suggesting is that, can't we make `fn` to be used in naming methods in
class? (this will be optional though),


I mean like:

```php

class Greet {

public fn __construct(
public string $name,
public string $city
) {}

private fn init(): string
{
return "Hello {$this->name}, From {$this->city}";
}
}

```

The above code looks cool, readable and less verbose, what is your opinion
on this?


[PHP-DEV] Re: Basic Type Alias

2023-10-29 Thread Oladoyinbo Vincent
So, who is going to help with the implementation :)

On Saturday, October 28, 2023, Alexandru Pătrănescu 
wrote:

> Hey,
>
> So actually while reading this:
>
> On Fri, Oct 27, 2023 at 11:42 PM Oladoyinbo Vincent 
> wrote:
>
>> And also, in order to group and namespace the Type Alias, i suggest we use
>> `typedef`, like i specify in my last message, it will be like this:
>>
>> File A.php:
>>
>> ```php
>>
>> namespace Package;
>>
>> typedef MyTypes {
>>
>> type Numeric: int|float|null;
>>
>> type Chars: string|null;
>>
>> type Result: bool|null;
>>
>> }
>>
>>
>  I came up with an idea:
>
> In php we don't have inner/nested classes, like in Java.
> But maybe at some point we could have. An inner class would help with
> avoiding some extra files and autoloading, especially when that class would
> be needed as private.
>
> Coming back to types, what if a type would be allowed to be defined on the
> class level?
> It would solve the autoloading problem as it would be loaded together with
> the class.
> And I guess that in real-life, complex types are usually related to some
> code using them, so I expect that identifying a class where the type to be
> placed would not be hard.
> And even if it would be difficult, There can always be a class named Types
> that would have only type definitions.
>
> An example would look like this:
>
> namespace My\App;
> class Types {
> public type Numeric: int|float;
> }
>
> And it could be used with:
>
> use My\App\Types.Numeric;
> function castNumericToFloat(Numeric $number): float {
> return (float)$number;
> }
>
> or
>
> use My\App\Types;
> function castNumericToFloat(Types.Numeric $number): float {
> return (float)$number;
> }
>
> or by using an import alias, of course.
>
> Maybe we can use this construct, along with allowing a type to be defined
> in a normal way, a way that would not permit autoloading.
> However, a way that would better fit code that is procedural and it can be
> loaded in the same functions.php that some projects use.
>
> Allowing inner "types" on classes might be a bit more complex that I can
> ever evaluate.
> But it might open the door for inner classes and there are nice constructs
> that can be built using this.
>
> Regards,
> Alex
>


[PHP-DEV] Re: Basic Type Alias

2023-10-27 Thread Oladoyinbo Vincent
So, we have to discuss and conclude on the best syntax to use for the Type
Alias:

Syntax 1:

```php

type T = int|string|null;

```

Syntax 2:

```php

type T: int|string|null;

```

Syntax 3:

```php

use int|string|null as T;

```

And also, we need a function to check of type exist, maybe `type_exists()`
will be a great choice :).

And also, in order to group and namespace the Type Alias, i suggest we use
`typedef`, like i specify in my last message, it will be like this:

File A.php:

```php

namespace Package;

typedef MyTypes {

type Numeric: int|float|null;

type Chars: string|null;

type Result: bool|null;

}

```

File B.php:

```php

declare(strict_types=1);

use Package\MyTypes;

class Hello {

use MyTypes;

public function A(Numeric $id, Chars $message): Result
{
// get the value
 echo Numeric::value; // int|float|null
}
}

```

Well, it's just the round up of every features listed in this discussion,
how is it? I will like to see your thought on this :).

Best Regards
O. Vincent.


On Friday, October 27, 2023, Mike Schinkel  wrote:

> > On Oct 26, 2023, at 3:23 PM, Larry Garfield 
> wrote:
> >
> > App-wide aliases run into the autoloading problem.  If the engine runs
> across the add() function above, and "numeric" isn't defined, what can it
> do?  Currently, all it can do is trigger autoloading, which only works for
> class-ish constructs (class, interface, trait, enum).  Making type aliases
> a full class-like construct seems... weird, and over-engineered.
>
> Curious, how do you define a "full class-like construct" in this context?
> Anything more than autoloading?
>
> And would autoloading actually require something to be a "full class-like
> construct," or could it not be something lighter weight (assuming full
> class-like constructs are not than just autoloading?)
>
> > But if not, how do we autoload them?  And if they do autoload somehow,
> does that mean we end up with a bunch of files with a single `type` line in
> them?  That seems not-good.  You also then have to ask how they interact
> with namespaces.
>
>
> Straw man proposal:
>
> When PHP recognizes a symbol in the context it would expect a type yet PHP
> does not recognize that type, PHP could use the existing autoload mechanism
> to determine files and directories in which those types might be located.
> This would address namespaces, I believe
>
> Then, following PSR 4 is could attempt to autoload via a file of the same
> name.  If there are types and classes, interfaces, traits and/or enums with
> that same name they would all need to be contained in that same named file,
> much as it currently works.
>
> Of course that would require one .PHP file per type which as you mention
> would not be ideal.
>
> So instead, a new PSR could be created to extend PSR 4 to add
> type-specific considerations. For example, when the type passed in is "Foo"
> it could first look for `/~types.php` and load it but it that did not work
> then it could look for `/~types/Foo.php`.  I picked the tilde (~) since it
> cannot be part of a valid namespace of class name so no backward
> compatibility concerns.
>
> If the type name passed to the autoloader is `Foo/Bar` then it could look
> in `/~types.php` first, if not there then `/Foo/~types.php` and if not
> there, then `/~types/Foo/Bar.php`.  I picked the tilde (~) since it cannot
> be part of a valid namespace of class name so no backward compatibility
> concerns.
>
> Having a single `~types.php` per namespace would let developers put all
> their types for that namespace there, if that is what they prefer. Or they
> could pull all types in the root's `/~types.php`.  Or they could create a
> file for each, whichever their preferences.
>
> I am envisioning a new `type_exists()` function would be required.
>
> Even better would be to add an additional optional parameter $type to
> my_custom_autoloader_new() which could either pass in a numeric for some
> new predefined constants like PHP_AUTOLOAD_CLASS=1,
> PHP_AUTOLOAD_INTERFACE=2, etc., or just a string like "class", "interface",
> etc.
>
> Based on that idea, such an autoloader might look like this:
>
> function my_custom_autoloader_new( $name, $type ) {
> $dir = __DIR__ . '/includes';
> switch ($type) {
>case PHP_AUTOLOAD_TYPE:
>   $file = sprintf("%s/~types.php", $dir);
>   if ( file_exists( $file ) ) {
>  require_once $file;
>   }
>   if (type_exists($name)) {
>  return;
>   }
>   $file = sprintf( "%s/~types/%s.php", $dir, $name );
>default:
>   $file = sprintf("%s/%s.php", $dir, $name);
> }
> if ( file_exists( $file ) ) {
>require_once $file;
> }
> }
>
> > So any type alias proposal would need to sort out the above "definition
> problem" in a way that's generally acceptable.  That's been the hold up for
> 3 years, I think.
>
> The above is potentially one way to skin that cat.
>

Re: [PHP-DEV] Basic Type Alias

2023-10-26 Thread Oladoyinbo Vincent
Since there may be need for reusability, I feel it can have this kind of
structure:

// File: A.php

```

namespace A;

typedef TypeLists {

type Msg = string|null;

type Numeric = int|float;

type MyClass = \Package\Test|\Package\Db;

}

```

// file: B.php

```

declare(strict_types=1);

use A\TypeLists;

class Test1 {

use TypeLists;

public function greet(Msg $message): Msg {
// ...
}

}


$init = new Test1;

// it triggers TypeError when strict types is declared
$init->greet(1); // TypeError

```

And for local usage only:

```php

typedef T = int|string|null;

// or

type T = string|int|null;



$msg = fn (T $message): T => $message;

echo $msg;

```

On Fri, 27 Oct 2023, 12:51 am Erick de Azevedo Lima, <
ericklima.c...@gmail.com> wrote:

> I'll use it a lot if they'll be namespaced. It avoids name-collision using
> the existing ecosystem and we already use lots of "uses" in our codes.
> When Enums came to the party, they came namespaced as traits, classes and
> interfaces. The last 2 represent types, concrete and abstract.
> User defined types are nothing more than types, so I think the way to gois
> to keep it namespaced as well.
>
> About the type compatibility, covariance and contravariance, let's say I
> define some type inside my package:
>
> // File: C1.php =>  My package code
>
> namespace N1;
>
> typedef MyString =
> string|Stringable|\Symfony\Component\String\UnicodeString
> ;
> typedef MyBool = null|bool;
> typedef BigNumeric = int|float|\Brick\Math\BigNumber;
>
> class C1
> {
> protected function myQuestionableFunction(MyString $str1): MyBool
> {
> //...
> }
>
> protected function myQuestionableFunction2(null|C1 $str1):
> ScalarNumeric
> {
> //...
> }
> }
>
> // File: C2.php => On the project of those who are using my package
>
> namespace N2;
>
> typedef ScalarNumeric = int|float;
> typedef Falsy = null|false;
>
> class C1 extends C2
> {
> protected function
>
> myQuestionableFunction(string|Stringable|\Symfony\Component\String\UnicodeString
> $str1): Falsy
> {
> //...
> }
>
> protected function myQuestionableFunction2(Falsy|C1 $str1):
> ScalarNumeric
> {
> //...
> }
> }
>
> I propose that this code should be valid code, because, in the end, these
> *typedef's*, are just synonyms.
>
> *Note:* By the way, I propose to use the C/C++ keyword, which is *typedef*
> and
> dropping the syntax* "type MyType = [string, null];",*
> which differs too from how typehints are used and do not add any benefits
> *.*
>
> --
> Erick
>


[PHP-DEV] Basic Type Alias

2023-10-25 Thread Oladoyinbo Vincent
Greetings to you all,

I will like to submit an RFC on introducing type alias to php.

Even though Generics won't or never be introduced to PHP, personally i will
like php to add the type alias feature.

Type aliases provide a mechanism to create more descriptive and readable
type hints in PHP code. This enhancement will improve code readability and
maintainability and also to promote type reusability.


Motivation:

The motivation behind introducing type aliases is to:

1. Enhance code readability by allowing developers to use meaningful type
hint names.
2. Improve code maintainability by reducing the likelihood of type hint
updates throughout the codebase.
3. Encourage the adoption of best practices for type hinting.


Proposal:

Syntax:

Type aliases will be declared using the `type` or `typealias` keyword,
followed by the alias name, an equal sign (`=`), and the type it is aliased
to.


Sample:

```
type MyType = string;

// or

typealias MyType = string;


// Advance

type MyType = string|null;

// or

type MyType = [string, null];

```


Usage:

Type aliases can be used in parameter and return type hints as follows:

```

function greetings(MyType $message): string {

// Implementation

}

greetings(1); // TypeError

```

Since this is just a basic feature, Type aliases Inheritance (compound
type) may not be added, since we are not digging deeper into generics :).



References:

https://docs.python.org/3/glossary.html#term-type-alias

https://doc.rust-lang.org/beta/reference/items/type-aliases.html

https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#type-aliases


So, What do you think?