[PHP-DEV] Custom object equality

2023-10-18 Thread someniatko
Hi internals,

There is often a need to compare whether two objects are equal. For
example, a popular [brick/money](https://packagist.org/packages/brick/money)
library has a `Money` class, which has an `equals()` method. However, this
becomes tedious to implement such methods, when multiple nested objects are
involved. For instance, Money has an amount and a currency.

There were already suggestions on the mailing list to allow "overloading"
existing `==` operator, and some suggestions went even as far as
overloading `<`, `>=` etc operators. However, overloading existing
operators may lead to a BC break between the PHP version which does support
the functionality, and which doesn't. It won't result in a BC break in case
it's an entirely new syntax, because a library or a project won't be able
to write code which overloads `==` in say PHP 8.4, but with code which
still works in PHP 8.3 - it will have to require PHP 8.4+. But if it is
implemented as a magic method, then `==` will work differently for 8.3 and
8.4.

I suggest thinking about introducing a new operator `~=`, which signifies
that custom equality is requested. In such a case,  `==` will work as it
works now, and by default `~=` will work also like `==`, unless its
behavior is overwritten via a magic method. If a magic method is not
present in a class being compared, `~=` will compare two objects field by
field, but using `~=` comparison rather than `==` comparison, recursively.

For instance, a Money object may consist of Amount and Currency. If two
Moneys are compared using `~=`, and Money does not implement a magic
method, Amount also doesn't implement it, but Currency does, then Amounts
are compared using  `~=` which is equal to `==` comparison in this case,
but Currencies are compared using their custom comparison logic.

This approach allows combining
- no BC break - `~=` is a new syntax which is unavailable in older PHP
versions
- explicitly showing an intent that objects are compared using a custom
comparison, rather than standard PHP one
- allow to skip writing boilerplate equals() methods which just forward
equals() to the nested objects
- standardize such comparisons on the language level

Of course how exactly this operator looks may be changed, `~=` is just an
example.

WDYT?

Regards,
Illia / someniatko


Re: [PHP-DEV] RFC Proposal: Readonly Structs in PHP

2023-09-08 Thread someniatko
Hi internals!

I think it can be useful for structured data obtained from decoding JSONs
or from a relational database. However, maybe there is an even better idea,
which combines the best of two worlds: the world of your structs RFC, and
native PHP arrays - something like "array shapes".

For instance, taking the syntax from your proposed RFC (but perhaps the
keyword changed to `shape`, or perhaps `array class` to reuse keywords -
let's not bikeshed here) to define a shape, and adding a function like
`array_shape_coerce($array, $shapeType)` which internally marks an array to
be of a defined shape if it matches its definition (throws an exception
otherwise, or perhaps returns true/false value or an enum for
success/failure) and allows it to be passed where a certain shape type is
expected. I think this could be a better approach than pure structs because
it leaves all array-based PHP machinery available to such "structs", like
`array_map()`, `array_filter()` etc.

There is an open question of whether array coerced to shapes can be
modified, and if yes, how to react to modifications. Perhaps the easiest
solution is to have another function along the lines
`array_shape_seal($array, $shapeType)` which not only marks array to be of
shape (if the given array matches given shape), but also permits only such
modifications which keep the array to be of this shape. And if the regular
`array_shape_coerce` is used, then any modifications are permitted, but the
array "loses" its shape.

Regards,
Illia / someniatko


Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-18 Thread someniatko
I am glad this topic arose! I was also planning to write on this topic to
the internals mailing list, but have abandoned this idea, because I feel it
might be inconvenient for the real active PHP developers on the list to
receive too many emails from the people which don't actively participate in
the development itself.

My interest in the pipe operator might seem a little non-standard -
basically what I'd really want to see is a **nullable** pipe operator!

There is a popular library github.com/schmittjoh/php-option, which has 250
MILLION installations. Basically what it provides is a class-wrapper of a
value of lack thereof: it's either `Some` or `None`. I also maintain
a similar library https://packagist.org/packages/someniatko/result-type
which fixes some shortcomings of the original one related to the static
analysis, but this is another story. Basically what the stats tell us is
that such stuff is popular among the PHP community.

In my eyes, it is actually semantically equivalent to the nullable PHP
types: `?Type`. And some operations provided by the lib, are actually
covered by PHP itself, which has multiple null-friendly operators:
`$option->getOrElse($defaultVal)` --> `$nullable ?? $defaultVal`
`$option->isEmpty()` --> `$nullable === null`
`$option->getOrThrow(new \Exception('blah'))` --> `$nullable ?? throw new
\Exception('blah')`

I'd like to use the arguably "more idiomatic" native PHP nullables, rather
than a foreign-feeling userspace construct, if they were more convenient.

But there is a very important operation, `map()`, which is unfortunately
not covered by the native PHP, which is `Option::map()`, and here is a
real-world example:
```
return $repository->getById($idFromHttpRequest)
->map($serializer->serializeToJson(...)) // only executes when the
Option is Some, not None
->map(fn (string $json) => new Response(status: 200, content: $json))
->getOrElse(new Response(status: 404));
```

I'd really like to write such code in a native way:
```
return $repository->getById($idFromHttpRequest)
?|> $serializer->serializeToJson($$)
?|> new Response(status: 200, content: $$)
?? new Response(status: 404);
```

Notice I use the old syntax here, using `$$` as a "piped" intermediate
result variable, mostly because I'd like to use arbitrary PHP expressions,
instead of piping functions only. I feel this is more natural for the PHP
than the more functional-oriented way. I am okay with using functions too
like this:

```
return $repository->getById($idFromHttpRequest)
?|> $serializer->serializeToJson(...)
?|> fn (string $json) => new Response(status: 200, content: $json)
?? new Response(status: 404);
```

but that feels less "clean", and also note the inconsistency with `?? new
Response(status: 404)` part.

Regards,
Illia / someniatko


Re: [PHP-DEV] [VOTE] Use exceptions by default in SQLite3 extension

2023-05-15 Thread someniatko
Got it, thank you for explaining.

Regards,
Illia / someniatko

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] [VOTE] Use exceptions by default in SQLite3 extension

2023-05-15 Thread someniatko
Hi!

It says in the RFC:

> PDO is using exceptions, like everyone else.

and

> Create a new exception class SQLite3Exception, which extends the Exception 
> class

The `PDOException` class is actually extending the `RuntimeException`,
not just `Exception`. I am sure it is better to do this for
`SQLite3Exception` as well.

Regards,
Illia / someniatko

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] Class Re-implementation Mechanism

2023-02-21 Thread someniatko
>
>
>> So it's mostly a syntactic sugar that allows defining an interface for
> the current class that is already implemented by the current class.
>

Yeah, while answering to you, I've actually came to the same conclusion.

>

> The interface name is the same as the class name and based on the context,
> you either use one or the other.
>

I think we should distinguish this thing from an interface though.

There are some places where this could get in conflict like (new
> ReflectionClass(A::class))->isInterface(). But also internally things might
> be difficult to sort out to know what to use one or the other.
>

Yeah, I also thought about reflection, exactly about this method. I believe
it's better not to lie, and make isInterface() return false. However,
another method should be added, e.g. isClassInterface() - which will return
true only in case of `class interface`, or, maybe a more general one like
isImplementable(), which will also return true for interfaces.


> To have a perfect syntax-sugar, why not also allow the interface name to
> be specified?
> Something like:
> final class interface(ServiceInterface) Service {
> public function method1() {}
> protected function method2() {}
> }
>
> that would generate:
> interface ServiceInterface {
> public function method1();
> }
> final class Service implements ServiceInterface {
> public function method1() {}
> protected function method2() {}
> }
>

Well that goes against my initial concern of not introducing additional
entities to the system. However it indeed reduces the amount of code to
write and is more "transparent" type of syntaxic sugar, like the promoted
properties in constructors - this feature also translates to PHP code. If
my suggestion ever becomes an RFC, this way of implementing it may become a
separate vote I suppose.


Regards,
Illia / someniatko


Re: [PHP-DEV] Class Re-implementation Mechanism

2023-02-21 Thread someniatko
> This sounds interesting but it breaks some expectations.
>
> Interesting because you can have any class act as an interface for other 
> classes with the interface being built up of any public properties or method 
> that exists on that class.

In my original suggestion, it's not like any class, but only those you
specifically mark as `class interface`, not just `class`. Closer to
the end of my idea I also suggest that maybe it's worth it to allow
implementing, like interfaces, ANY classes, not only those
specifically marked with the new syntax, but this indeed brings up
some issues.


> Ok, maybe not any class but just a final class.

I see no issue there of allowing to reimplement the interface of a
non-final class. This still is better than extending from it IMO. But
we _probably_ should prohibit it from abstract classes.


> And also maybe just a final class that doesn't yet implement an interface.

Also, here is no conflict as well. When reimplementing the interface
of the class, you can treat it as a normal interface - which can
extend from other interfaces.


> The expectation it breaks is that if you have a final class, whenever you use 
> it, you expect some specific implementation exists on it.
> And this would break the expectation and in real life someone might pass a 
> totally different implementation.
> Will not break generic LSP but still will break some expectations.

That's why a new syntax is brought up. This expectation might indeed
break if we allow to reimplement any existing final class, instead of
requiring a manual opt-in.

(sorry, this email is sent to you the second time, Alexandru, because
I forgot to reply to the maillist as well)

Regards,
Illia / somenitko

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



[PHP-DEV] Class Re-implementation Mechanism

2023-02-21 Thread someniatko
Hi again, internals

My marathon of some crazy ideas continues :D, with less crazy one this time.


## Idea

Allow "reimplementing" the non-static public API (that is public
properties and methods, excluding constructor) of a class by other
classes like this:

```php
final class interface A {
public string $s;

public function __construct(string $s) { $this->s = $s; }

public static function fromInt(int $i): self { return new
self((string) $i); }

public function foo(): int { return 42; }
}

final class B implements A {
public string $s = 'hello';

public function foo(): int { return 69; }
}

function usesA(A $param): void {}

usesA(new B); // this works
```


## Explanation

Consider there is a class like this:

```php
final class Service {
public function __construct(private SomeDependency $dependency) {}
// ...
}

final class SomeDependency {
// ...
}
```

We want to write some tests for the Service class, but we don't want
to use a real SomeDependency instance
during tests. A common approach is to either extract an interface
(JUST to make it testable), or to drop the
`final` keyword and allow extending the class.

Both approaches have their flaws:
 - extracting an interface unnecessarily complicates the system, where
only one "real" implementation of an interface is assumed.
 - dropping the `final` keyword allows for the rabbit-hole of
inheritance abuse, like greatly described in this article:
https://front-line-php.com/object-oriented

I believe I came up with a better idea: what if we could leave both
benefits of prohibiting the inheritance abuse and also allow not to
clutter our namespace with excess entities like interfaces? I hereby
suggest to combine the responsibilities of a class and an interface
into one thing like that:

```php
final class interface C {}
final class D implements C {}
```

Now other classes can "implement" this class as well. Introduction of
the new syntax (`class interface`) also solves BC problem - if you
want to forbid your classes to be reimplemented whatsoever, you can
still stick to the `final class` syntax. Although it is also possible
to allow "reimplementing" ANY class, then new syntax is not needed -
but some library writers like Marco Pivetta could be sad about that I
suppose.

Soo..., what do you think? Could this be a valuable addition to the language?

Regards,
Illia / someniatko

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC Proposal - Types for Inline Variables

2023-02-06 Thread someniatko
Hi there,

I am not a core PHP language developer, just a regular PHP programmer, and
cannot speak for the whole community, so I'll just share my opinion.

I believe a new language feature suggestion should contain not only its
description, but also motivation: i.e. what are we trying to achieve with
it. Will the development experience be worse without it, or maybe it
disallows some sneaky bugs to appear in your code, or maybe it acts as a
native documentation for your code etc.

Personally it's hard for me to see what kind of improvement will
restricting a type of a variable bring. It may prevent repurposing the
variable with the same name for a different use somewhere down the
function, which can lead to bugs if a function is large enough. However,
for such cases I think better idea would be to introduce `const` variables
like in JavaScript - which can only be set once and cannot be reassigned
later. This way you'll also guarantee the type of the variable will be
preserved.

> We can add types in a lot of places, but we still don't have a way to add
types to inline variables.

> int $value = 10;
> $value = 'foo'; // TypeError

Can you describe some use cases where this feature will be useful? I see
it's coming from statically typed / compiled languages like C++, but in
such languages compiler must know variable type in order to manage memory
properly. As PHP is an interpreted  language, it doesn't have this problem.

Regards,
Illia / someniatko


Re: [PHP-DEV] Re: Official Preprocessor

2023-02-04 Thread someniatko
Hi,

These all are valid concerns! I cannot speak about management and cost
issues though, as I am not an active PHP dev team member.

> 3. What's the MVP? How do we measure usefulness, adoption and maintenance 
> complexity?

As a shot in the dark, the first step could be implementation of typed
lists in my opinion. Do not implement full-blown static analyser nor
the type checker for each possible case, just only check the usage of
typed lists within the pre-processed files. Assume that whatever comes
from the non-preprocessed ones is correct. Make only simple naive
assumptions for all internal array_ functions as well as basic array
operations. If there is some runtime magic going on with constructing
the list, just fallback to infering the type as a simple array. For
such cases, allow a special attribute which will tell the type checker
this variable / property etc will indeed contain the typed list, like
a @var annotation for IDEs / static analysers nowadays.

The preprocessor / type checker **should not aim to 100% guarantee the
correct types will be in the runtime**: TypeScript does this neither.
Rowan has mentioned Dart language in a parallel thread, which makes
most of the checks statically, but for some cases the compiler still
adds runtime checks. Rowan warned that PHP might have a lot of such
cases possible though. But I still think this also might be a good
idea for MVP.


> 4. Is it an aborttable idea? If things go south and can't be supported 
> anymore, how bad for PHP adopters would it be?

I don't think any of PHP new features that go live are abortable. This
affects not only my suggestion, but also everything what has been done
for PHP in past. Once a feature is in the language and released to the
public, you cannot revert it. There must be a long multi-year process
preceded with a deprecation at least. A concept of experimental
features was suggested earlier, but this is completely different
topic, so I believe we should not go into that rabbit hole here.
Overall, I consider this question orthogonal (or irrelevant if you
prefer) to the original topic, let's take as an axiom that there is no
way back.


> 5. How would voting on the spec be like? Complete years-work-hours spec or 
> small incremental functionalities?

Small incremental functionalities. Gradually more stuff could be
proven statically, more complex cases covered, and while they are not,
an attribute / static assertion could be used. Maybe some of such
assertions could be allowed to be preserved in runtime, at the cost of
some performance penalty, IDK. But I believe we should leave such
choice to developers, whether they want the checks in runtime as well.


> 6. Is versioning tightly coupled with PHP version or does it have its own 
> version support system targeting multiple php versions at the same time?

I strongly believe it must go hand in hand with the PHP version, and
not as a separate tool, because I see it as a feature of a PHP
language itself.


> Overall, I think PHP has been constantly losing popularity in favor of 
> Typescript and a transpiler could create an exciting solution for some of 
> PHP's problems, but it does not seem like a pet project.

Sure, it should be considered seriously and requires some upfront
planning. Though, well, PHP itself started as a pet project :D

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



[PHP-DEV] Re: Official Preprocessor

2023-02-02 Thread someniatko
I'd like to also emphasize that the concept of compilation and static
type-checking / analysis is not foreign to the PHP community. Major
frameworks like Symfony already have a concept of compiling e.g. a DI
container, and static analyzers like Psalm, PHPStan and others are
actively used.

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



[PHP-DEV] Official Preprocessor

2023-02-02 Thread someniatko
Hi Internals

The main gist:
--

I suggest to introduce an official type-checker / static analyser /
preprocessor / transpiler for PHP, somewhat similar to TypeScript in
the JavaScript world, which will allow to introduce the features
otherwise impossible for the PHP world, at the cost of including an
additional transpilation step.

The reasoning:
--

You all know there are a lot of problems with the language, especially
large gaps with the current type system, which have large community
demand to overcome, but still cannot be solved due to the paradigm
chosen by PHP. And the paradigm is to be statically typed (to some
extent), but dynamically checked language, which limits the number of
available options due to performance reasons.

The introduction of static types have gradually eliminated the need of
using external means of communicating the types (phpdoc @param and
@return annotations), replacing them with native language constructs,
making the language more expressive and enterprise-ready. However,
there are a lot of things still missing, like types of arrays,
including lists, hash-maps and structure-like arrays, and of course
generic classes and functions. These are still covered nowadays with
external means like phpdoc annotations and static analysers / type
checkers to validate them. This leaves PHP in the odd mixture of
native types and externally validated annotations via comments.

Paradigm of a dynamically checked language also leaves out the problem
of type-checking before running the code. Even though the types are
defined statically, you still have to physically run the code, with
all possible execution paths, to catch a type error. To avoid that you
still would have to use an external typechecker / static analyser,
even if PHP could cover 100% of type demand natively.

Python solves this problem nicely I think. It is dynamically typed,
but it allows a special syntax for static types and also has a
separate static type checker. I think this is really a good approach
and it would be great if PHP followed this path for the beginning, but
we have what we have already.

There were attempts to create preprocessors for PHP (like PHP++ IIRC),
which allowed features like generics, but they did not gain enough
popularity, weren't baked by large enough companies, didn't make their
way to major IDEs support. I believe the only solution is to make an
official one.

Therefore, I suggest the following thing:
1. Introduce a new #declare directive which will mark the file as
requiring pre-processing.
2. Let PHP introduce special features that only work in such
"pre-processing required" files, such as typed lists and generics.
3. Implement a static type-checker in PHP that will verify those typed
lists and generics are indeed used in a valid way.
4. Make the PHP preprocessor output the "normal" PHP file somewhere,
which has list types and generics erased. I think something like that
was suggested earlier many times.

As an alternative to a new #declare feature + validation +
transpilation in "plain old PHP", the Python way of just ignoring
statically checked stuff could be applied. This approach though looks
odd to me in PHP world, because having some stuff checked in runtime,
and some only statically may confuse developers a lot.

Basically, this will split PHP in two languages, one being superset of
other, but checked statically. I realize this might be much of a
paradigm shift, it may require lots of work if accepted (I can only
dream of it though), but still I want to share my thoughts with you
and propose something for consideration.

Regards,
Illia / someniatko

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] [RFC][Dynamic class constant fetch]

2022-11-04 Thread someniatko
> What's convenient about `Foo::{$bar}` vs `constant(Foo::class . '::' .
> $bar)`? I'm a bit confused by this :|
>
> Is it the few keystrokes added?

Even if ignoring syntax / convenience bikeshedding, I find it a really
valuable addition to the language self-consistency. It's symmetrical
to the already existing syntax of dynamic property fetch and dynamic
method calls. One could argue that it's dynamic, too much magic and
bad, but then we should either deprecate those features, or if not,
have this symmetry. The Principle of Least Amusement and human pattern
recognition overall with thank you.

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] ARRAY_UNIQUE_IDENTICAL option

2022-11-03 Thread someniatko
> To solve this, I propose adding an ARRAY_UNIQUE_IDENTICAL option that
> can be passed to array_uniques $flags which uses identical operator
> (===) semantics. Internally it uses a new hashmap that allows using
> arbitrary PHP values as keys to efficiently remove duplicates. This is
> slightly over-engineered for this use case. However, this data
> structure will be required for implementing ADTs to deduplicate
> instances with the same values. This hashmap is a heavily minimized
> version of the teds extensions StrictHashMap [1].

As a regular developer, I look from the usage side, not from the
implementation side.
>From such perspective, remembering that filtering unique enums
requires this exact flag
is somewhat "dirty": on the surface, nothing tells that enums are
non-comparable.

You will have to memorize yet another PHP quirk, or be able to build a
logical chain:
- enums are non-comparable by default
- enums have no default string value (if not baked by a string)
- array_unique internally sorts an array
- default flag for array_unique compares the string representations of its items
- thus it won't work for enums in a general case

This requires deeper knowledge of PHP, which is for sure a valuable
skill, but not as wide-spread
as we would like to. Most of the devs will first try to use
array_unique() with the default flag, perhaps
not even knowing about flags existence. Each usage of such a flag will
not reveal intent by itself
and at least will require a comment for readable codebases.

Perhaps an alternative idea is to provide a default string value for
enums which are not baked,
Nikolas had already brought up this idea earlier.

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] is_literal

2021-06-14 Thread someniatko
Nevertheless, I am sure even without a dedicated type it is still a
valuable addition to the engine. Just to clarify, I understand that if
this would require too much additional work to implement the type, IMO
it's okay to ship the feature without it for now. I was just replying
to other arguments, which are not related to the work amount :P

Thank you for your work!

Regards,
someniatko

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] is_literal

2021-06-14 Thread someniatko
> And I agree, there would be value in having a `literal-string` type, 
> especially when working with IDE's and Static Analysers; but it brings a 
> couple of issues that the is_literal() function solves:

Yeah, those are valid arguments why we should have a dedicated
`is_literal()` function, and in fact we could have both the type and
the function at the same time, the same as we have `string` type and
`is_string()` function. My worry is, if type is not added in the
present RFC, adding it later may look as "too low value" and probably
will have a lower chance of being accepted.

> 1) Libraries need to support older versions of PHP, so they wouldn't be able 
> to use the `literal-string` for many years; whereas they can use 
> `function_exists('is_literal')` today, probably to provide their own function 
> that simply returns true on pre PHP 8.1.

If the type is added in say 8.2, they wouldn't be able to use it even
longer. Of course this can be re-modelled using a value object which
performs the is_literal() check in the constructor, however I think a
native PHP type would be better, for example in the case of variance
checks (being a subtype of "string").

> 2) The is_literal() function gives the libraries a choice on how to handle 
> the situation. At the moment they just receive a string of unknown origin, so 
> they can trigger a warning, while also supporting legacy projects who want to 
> switch off the warnings. And some developers might want to use a library that 
> has an option that can raise exceptions (so they can be certain there are no 
> issues).

If we have both the fn and the type, libraries would still have that
choice, either enforce it solidly and throw TypeError (PHP 8.1), or
polyfill the `is_literal()` function to always return `true` and be
able to both take advantage of PHP 8.1 and work on the earlier
versions.

I hope these points will be really considered, and PHP's type system
will evolve into more robust and strong one. (offtopic: hoping we will
have typed vector and dict types someday too)

> Craig

Regards,
someniatko

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] is_literal

2021-06-13 Thread someniatko
Hi!

>From what I understood reading the RFC, this looks like a new type,
"literal string", specifically a subtype of "string". Have you
considered instead of forcing library authors to use `is_literal()`
check everywhere on their input boundary and making sure no place
where input is passed, is forgotten, to let them type their whole
codebase, including internal, against the new `literal-string` type,
which would be enforced by PHP all the time? From my perspective as a
PHP developer, it would serve clearer intent than only checking in a
few places which presumably may take user input, i.e. you could
explicitly state "this function does only work with literal strings".

Regards,
someniatko

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] Re: [RFC] Short functions, take 2

2021-05-31 Thread someniatko
> Unless there is any significant feedback, I'll be calling a vote for this RFC 
> sometime late this week (Thursday/Friday-ish).

Hi! As a regular PHP developer, I am very interested in having this
quality-of-life feature: it allows code whose intent is more
functional-ish (mapping input arguments to an output expression), than
imperative-ish (do this then do that), to look more appropriate. Is it
planned to be voted or it's just forgotten :P?

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] A little syntactic sugar on array_* function calls?

2021-05-25 Thread someniatko
> The proposed syntax
>
> $array |> array_map($fn1, ?) |> array_filter(?, $fn2)
>
> When I compare to:
>
> $array->map($fn1)->filter($fn2)
>
> 1. It's longer. Much longer.
> 2. It still requires knowing where the array goes. That's legacy which we 
> could sidestep with the arrow notation.
> 3. Admittedly, the pipe is much more powerful.

While the argument No. 2. is completely valid, the 1st one is not so.
If you remove whitespaces around the `|>` and also if you alias these
functions to `map` and `filter` respectively (or if, for instance,
some future RFC moves them into a special `PHP\Array` namespace, which
would probably never happen, but it's allowed to dream), it could look
like this:

```php
$array|>map($fn1, ?)|>filter(?, $fn2);
$array->map($fn1)->filter($fn2);
```

A bit longer (due to 2.), but not that much, actually.

Best wishes,
someniatko

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] A little syntactic sugar on array_* function calls?

2021-05-25 Thread someniatko
> The pipe operator feels like a poor solution while `->` would do exactly what 
> people want.

Could you elaborate? Adding method-like array access functions with
only few predefined functions, and only for arrays looks very limited
in scope, while the pipe operator would allow applying any existing
function, be it internal or userland one, to any type of variable, not
limited by arrays, having the same "fluent api" feel. Also it clearly
distincts between object method calls and function application, which
is a plus for clarity, IMO.

I am also not sure who the "people" you refer to are, because, well, I
am among the people using PHP daily, and I would personally prefer a
more generic solution, which the Pipe Operator currently is.

Best wishes,
someniatko

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] A little syntactic sugar on array_* function calls?

2021-05-25 Thread someniatko
Sorry, I made a typo here. In combination with the proposed Partial
Function Application RFC
(https://wiki.php.net/rfc/partial_function_application), which is
however is under active discussion, and changes will probably be made
to it, it would look roughly like this:

```php
$array |> array_map($somefunction, ?);
```

Best wishes,
someniatko

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] A little syntactic sugar on array_* function calls?

2021-05-25 Thread someniatko
> I was wondering whether $array->map($somefunction) would be possible.

There is Pipe Operator RFC existing already, which most probably would
suit your needs. The code you want will look like this:
https://wiki.php.net/rfc/pipe-operator-v2

```php
$array |> array_map($somefunction).
```

Best wishes,
someniatko

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Partial function application

2021-05-13 Thread someniatko
> The GitHub PR supports this, and there is even a comment there saying
> we should show this in the RFC. We'll get that updated.

Thank you for the quick reaction and for your work!

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Partial function application

2021-05-13 Thread someniatko
> Greetings, Internalians!
>
> I would like to offer for your consideration another RFC, specifically syntax 
> for partial function application.
>
> https://wiki.php.net/rfc/partial_function_application

Thank you again for one more wonderful language change! I am sure this
is a huge step into the correct direction for the language. One of the
nice side effects of this proposal is that it is great for reducing
visual clutter when being used in functions like `array_map()`,
`array_filter()` etc. However, I have a small nitpick, which may
probably be a bit hard to implement: what about partially applied
constructors? They are sort of functions as well. For instance:

```php
$strings = [ 'value-1', 'value-2' ];
$objects = array_map(
fn (string $s) => new ValueObject($s),
$strings
```

to be turned into
```php
$strings = [ 'value-1', 'value-2' ];
$objects = array_map(new ValueObject(?), $strings);
```

There is unfortunately no mention of partially applied constructors in
the RFC. If it is not implemented as above, could you please consider
adding it to the Future Scope probably?

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Pure intersection types

2021-03-23 Thread someniatko
> Should we be planning ahead for some future where union and intersection 
> types can be mixed and design the reflection API accordingly?  I worry that 
> if we have a ReflectionIntersectionType, and a ReflectionUnionType, that 
> ReflectionIntersectionAndUnionType is just going to make both implementers 
> and users table-flip.

As far as I understood, there is no need for any new "combination"
`ReflectionType`-s. For e.g. "A|(B)". There should be a structure
like this:

```
ReflectionUnionType#getTypes():
|-- ReflectionType
|-- ReflectionIntersectionType#getTypes():
|-- ReflectionType
|-- ReflectionType
```

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



RE: [PHP-DEV] [RFC] Short-match

2020-12-16 Thread someniatko
`match` is an expression, where as if-else construction is not. This
allows for combining it with a potential future feature of single line
functions and methods. For example (hypothetical syntax is used):

```
function getNumberKind(int $number) => match {
$number > 0 => NumberKind::POSITIVE,
$number == 0 => NumberKind::ZERO,
$number < 0 => NumberKind::NEGATIVE,
}
```

See how natural it looks and reads.

Another improvement is that it reduces the amount of visual clutter
(`if` and `return` keywords).

Yet another distinction between “if” and “match” is their intent. `If`
is more appropriate for the procedural flow. However, when we operate
with pure functions, `match` is a good sign of such function. It shows
that different input values turn into different output values, instead
of different branches of procedural code being executed. Therefore, if
code is intended to be more FP-ish, IMO, `match` is preferred. For the
procedural code patterns, including early returns / throws, `if` is
clearly a better choice.

So, `match` is better suited for functional-ish parts of code, which
do not pose behavior, but only convert one value to another ones. In
the FP world, pattern matching is a widely used feature, allowing to
split computations of output value for different kinds of input value.
The closest thing available in PHP these days is `match (true)`. The
`(true)` part looks ugly and artificial, and removing it is a matter
of a cosmetic change.

Of course, it is possible to use `match` instead of `switch` or `if`s
for procedural code, and vice versa, which is still syntaxically
correct, but bad from an intent expression perspective. This is a
downside of `match` expression as a whole and, IMO, is irrelevant for
this small improvement.

So,
- `match` allows writing clearer code when used with FP-ish intent; it
is also an expression, therefore irreplaceable with if/switch in some
cases.
- pattern matching is a widely used feature in FP, and `match (true)`
is the current way to achieve the most similar thing in PHP.
- improving `match` will not hurt the language allowing to write the
same thing two ways – because it is already done by accepting `match`
RFC itself

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] [Discussion] Shorter Attribute Syntax Change

2020-07-29 Thread someniatko
Hello Internals,

Here is a small comparison table based on current feedback, maybe it
will bring some objective clarity to the discussion:
(markdown below)

Impact|`@@`|`#[]`
---|---|---
BC break|virtualy nonexistent|slightly broader: `##[` comments are now broken.
Parser|no technical problems by now|no technical problems by now
Extendability|less future-proof, arguably|more future-proof, arguably
Grepability|harder, arguably|easier, arguably (however, consider an
Attribute taking an array `[]` parameter.)
Perception|similar to PHPDoc annotations, more familiar to PHP
devs|more familiar to Rust devs

Other issues are either speculative or insignificant (as for me):
- causing future parsing issues: no evidence
- "backfilling": there is, arguably, no use case for it. Code using
PHP 8 features will target PHP 8 anyway. Code, compatible with both
PHP 7 and PHP 8 would most probably use classic PHPDoc annotations.
- "syntax no other language uses": this is probably insignificant.
- "possibility of @@ moving to @ is near to 0": i am not sure anyone
planned to move @@ to @, and if so, it would be an unnecessary BC
break.

I am personally in favor of `@@`, but just because it looks visually
nicer to me. I see no strong objective reason to favor one over the
other. If you want an ending token, maybe consider `@@Attribute@@`,
personally I like those round-ish shapes :P.

On Tue, Jul 28, 2020 at 5:47 PM Joe Ferguson  wrote:
>
> Hello Internals,
>
> I've been working with Derick Rethans and others (thanks all!) on a Shorter
> Attribute Syntax Change RFC which outlines reasons why the "#[]" syntax
> would be preferred over the currently agreed upon "@@" syntax for Shorter
> Attribute Syntax.
>
> An important part of the research that went into this proposal demonstrates
> how "@@" will make handling attributes more difficult for PHP_CodeSniffer
> (and similar tools) and shows how the alternative "#[]" syntax is more
> friendly for these tools.
>
> You can find the RFC
> https://wiki.php.net/rfc/shorter_attribute_syntax_change and I'm happy to
> answer any questions as best I can.
>
> --
> - Joe Ferguson
> JoeFerguson.me
> osmihelp.org

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] Re: [RFC] [VOTE] Make constructors and destructors return void

2020-07-09 Thread someniatko
> I think going from forbidding
> return types on ctors to requiring them to be void is one step to far.

I am afraid you've slightly misunderstood the intention of this RFC.
It is proposed that it is impossible to return anything from the
constructor, not that you have to add ": void" to it.

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] Re: [RFC] Nullsafe operator

2020-07-08 Thread someniatko
> I've reworded some things and added more information on short
> circuiting. Functionality wise the RFC has remained the same.
>
> Since there was little negative feedback I'd like to put this feature
> to a vote in ~1 week. If you have any concerns or criticism please let
> me know in time.

Just curious, do you plan on putting this to a vote in near time? The
feature freeze is coming soon.

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] Proposal: A way for classes to define a response to any primitive type cast

2020-07-08 Thread someniatko
> This would seem to fit your use case with Shoop quite well:
> rather than Shoop::array($array)->first()->unfold(), you would just call
> $array->first(). It's fairly high on a lot of people's wish lists, but
> there's a lot of details to get right in both design and implementation,
> so I strongly recommend searching for previous discussions and proofs of
> concept before diving in.

We don't need methods on non-scalar objects, if we have [pipe
operator](https://wiki.php.net/rfc/pipe-operator-v2): sth like `$array
|> array_first(?)`. This would allow much greater flexibility.

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Property write visibility

2020-06-30 Thread someniatko
I do agree with Marco that this is a step in a wrong direction. Our
goal should be not ensuring that a prop is not rewritten outside, but
rather that it is not re-written at all. It makes no sense to rewrite
a property in majority of cases:
1. fields of an DTO - nay. Should be immutable instead. You never
change DTO, don't you?
2. injected services (like DB connection or an HTTP client) - nay.
Shouldn't ever be overwritten once an object containing them is
instantiated. Write-once / immutable is preferred.
3. data fields of an Entity-like object - looks like the only
reasonable case. However adding dedicated syntax for this is arguably
not much better that what we have now. It is already solvable with
standard getX() pattern, or with a single method returning a required
chunk of state as DTO.

So for me this does only solve the problem of having getters (or
dedicated methods) in #3, which is rare enough compared to other code,
and is already solvable with syntax existing nowadays already.
Introducing the new syntax, however, will have the following
downsides:
- adding proper immutable / write-once properties to the language will
be met with much more resistance: "Why adding immutable if we have
private set already!"
- this will encourage using them in places where immutability (e.g.
via static analysis tool like Psalm) should be used instead (see #1
and #2).
- adding more advanced property accessors feature will be also likely
met with more resistance.

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php