Re: [PHP-DEV] [Early Feedback] Pattern matching

2024-06-23 Thread Hendra Gunawan

public string $lastName is @RE(GP::LENGTH_PTRN)
& @RE(GP::FORBIDDEN_CHARS_PTRN)
& @RE(GP::FORBIDDEN_WORDS_PTRN);


//  these are hard to maintain
public string $firstName is /COMPLEX_NAME_PTRN/;
public string $lastName is @RE(GP::COMPLEX_NAME_PTRN);
}
```

7. I noticed that ```as``` is tightly coupled with exception. Can we
suppress this exception with ```??```?

```
// it is weird to see this statement (as show in the proposal)
$value = $foo as Foo {$username, $password};

// these statements are more make sense
$foo as Foo {$username, $password};
$foo is Foo {$username, $password} ?: throw new Exception();

// if it can be suppressed, "as" is more valuable than what people think.
$newRect = $rect as Rectangle{width: <=10, height: <=5} ?? new
Rectangle(width: 10, height: 5);
```

8. Is there any type checking for object property pattern?

```
class Circle {
public int $radius;
}

// this statement will always fails unless there is type checking
$circle is Circle{radius: "10"};
```

~

4 of the 8 points I discussed above are related to range pattern and
regex pattern. Both are used daily. From my point of view, literal
pattern is no more special than range pattern and regex pattern. IMO,
both should be placed in Core patterns section, not in Possible
patterns section.

Regards, Hendra Gunawan.


Re: [PHP-DEV] [Early Feedback] Pattern matching

2024-06-23 Thread Hendra Gunawan
p; @RE(GP::FORBIDDEN_WORDS_PTRN);


//  these are hard to maintain
public string $firstName is @RE(GP::COMPLEX_NAME_PTRN);
public string $lastName is @RE(GP::COMPLEX_NAME_PTRN);
}

7. I noticed that ```as``` is tightly coupled with exception. Can we
suppress this exception with ```??```?

```
// it is weird to see this statement (as show in the proposal)
$value = $foo as Foo {$username, $password};

// these statements are more make sense
$foo as Foo {$username, $password};
$foo is Foo {$username, $password} ?: throw new Exception();

// if it can be suppressed, "as" is more valuable than what people think.
$newRect = $rect as Rectangle{width: <=10, height: <=5} ?? new
Rectangle(width: 10, height: 5);
```

8. Is there any type checking for object property pattern?

```
class Circle {
public int $radius;
}

// this statement will always fails unless there is type checking
$circle is Circle{radius: "10"};
```

~

4 of the 8 points I discussed above are related to range pattern and
regex pattern. Both are used daily. From my point of view, literal
pattern is no more special than range pattern and regex pattern. IMO,
both should be placed in Core patterns section, not in Possible
patterns section.

Regards, Hendra Gunawan.


Re: [PHP-DEV] [RFC] Property hooks, nee accessors

2023-05-15 Thread Hendra Gunawan
> Secondary votes are generally discouraged.  I can see the argument for 
> wanting a short-short version of set, given how common the validation use 
> case is, but => is almost universally the "evaluates to" symbol, so using 
> that for a set operation rather than get just feels weirdly inconsistent.  If 
> there were a set-only shorthand, it should be something else.
>
> That said, the ideal for validation would probably be guard clauses, like 
> this, but that would be a completely different RFC for another time.
> ```
> function foo(string $name where strlen($name) < 10) { ... }
>
> class Foo {
>   public function __construct(
> public string $name where strlen($name) < 10;
>   ) {}
> }
> ```
```guard``` seems a subset feature of ```hook```, although you want to
expand its use case in parameter. Property and parameter are variable.
If ```guard``` can be implemented in both case as you write above,
theoretically  ```hook``` can be either. I will choose ```hook```
rather than ```guard``` to anticipate future expansion. Isn't it
better to choose one broad concept than many?

I found a contradiction here. Previously you said that:
> ... the problem with omitting the {} is that it creates yet another syntax 
> variant. That makes it harder for the parser, for static analyzers, for 
> user-space parsing tools like php-parser, etc. That's more work for everyone 
> for fairly little gain.

And here, you introduce a syntax variant. Is it really significant if
we introduce a new ```where``` keyword ```compared to the already used
```get``` keyword? I will clarify here in case there is
misunderstanding:
* If we have more than one hook per property, then the syntax will be
the same as proposed by RFC.
* If we have only one hook per property, than the syntax are:
```
public function __construct(
  public string $prop1 get => strtoupper($this->_prop1),
){}

public function __construct(
  public string $prop2 set => $field = strtolower($value),
){}

public function __construct(
  public string $prop3 get {
$temp = strtoupper($this->_prop1);
return substr($temp, 0, 10) . '...';
  },
){}

public function __construct(
  public string $prop4 set {
$temp = strtolower($value);
$field = substr($temp, 0, 10);
  },
){}
```
Note: Please ignore any error. The ending comma is actually part of
the parameter list, not a hook. So it becomes optional if the param is
only one or it is the last param.

All the examples are constructor property promotion, because that is
my only concern. Because the space is limited, the more consistent the
code, the better. If I have to write hooks outside CPP, I don't mind
using the other syntax. There's plenty of room to fill, and
consistency is tolerable.

Should we postpone the implementation of the shortest version?
Hopefully we have enough time to decide which one will be implemented
next.

>
> ... Ilija also noted to me off-list that you could also have a set hook that 
> throws an exception rather than just being null, which would also work to 
> prevent writes.

Such a coincidence. I was going to revise my code:
```
// cache once and freeze,
// and without additional hidden property
// in case asymmetric visibility in not implemented yet
public string $prop1 {
  get => $field ??= $this->heavyTask($this->propx, $prop->y);
  set => throw new Exception("prop1 is read only");
}
```

> I think an unset hook is a fine addition in the future.  The way the code is 
> implemented it should be straightforward to add.  However, it feels like 
> scope creep to include it right now, especially when there are workarounds 
> available.  If there's a clear consensus from voters to include it, though, 
> we can consider that.  (Meaning, anyone that would favor including an unset 
> hook now, speak up or we'll assume it's better to stick with just get/set for 
> now.)

+1 for including ```unset``` as part of this RFC.

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



Re: [PHP-DEV] [RFC] Property hooks, nee accessors

2023-05-15 Thread Hendra Gunawan
> (Also, when replying, please please remove duplicate names from the to/cc 
> line.  I just got double copies of everything in this thread this morning.  
> I'm on the list, I don't need to be CCed.)

Sorry about that. Not my habit before.

> For the second, the problem with omitting the {} is that it creates yet 
> another syntax variant.  That makes it harder for the parser, for static 
> analyzers, for user-space parsing tools like php-parser, etc.  That's more 
> work for everyone for fairly little gain.

Sad to read that. Making one of them as the shortest shorthand feels
like a picky decision. Some people agree with ```get```. Some people
will argue that ```set``` deserves more than ```get```. Personally, I
choose ```set``` to be the shortest shorthand as it is more relevant
with constructor property promotion and value object. Do we need a 2nd
vote for this one?

> Removing the {} entirely from all forms makes it harder to denote where the 
> list of hooks begins and ends.  They would probably have to be 
> comma-separated, like this:
>
> public string $foo
>   get { return $this->bar; },
>   set { $this->bar = $value; };
>
> Which I'd argue is harder to read anyway, because you have to be careful of 
> the very small , and ; marks.  The {} is just easier for humans to parse as 
> well as the machine.

Looks like it's not more simple compared to the other one.

> What we really would need here is asymmetric visibility.  No set hook, but 
> make the property private(set) so that trying to write to it gives an error, 
> as it should.

So if asymmetric visibility is implemented, will my code be this simple?
```
// cache once and freeze,
// and without additional hidden property
public private(set) string $prop1 {
  get => $field ??= $this->heavyTask($this->propx, $prop->y);
}
```

>  For cache clearing, the best way to do that is probably with an unset hook.  
> That's been omitted from the RFC for now for simplicity, but that sounds like 
> it would be an argument to introduce it later.

I was going to write about this one. IMO, why do we need to provide
additional hidden properties, when we are able to store the cache
directly into it? Obviously we need a ```unset``` hook.

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



Re: [PHP-DEV] [RFC] Property hooks, nee accessors

2023-05-15 Thread Hendra Gunawan
> If there is no forward compatibility consideration, can we simplify
> interface definition to this one?
> ```
> interface IFace
> {
>   public string $readable;
>   public string $writeable;
>   public string $both;
> }
> ```

After carefully reading the proposal again, I think I know the answer
for my own question.

Short answer: no, we still need ```{ get; }``` to enforce the implemented class.

There are two different things here:
1. enforcing the implemented class
2. enforcing the caller site

If there are only ordinary properties, then ```{ get; }``` is truly
useless at the moment. On the other hand, virtual properties need
rules to be enforced, since there is no default hook given to it.

Since PHP lacks method definition enforcement at the caller site, I
assume that property would suffer the same.

Since we don't know what type of property is in the caller site,
static analysis tools can benefit from ```{ get; }``` to produce a
warning that we should not assign value to the property. A more
complex check should be performed to the implemented class because the
property type can be determined directly (if i am not wrong).
```
interface IFace
{
  public string $readable1 { get; }
  public string $readable2 { get; }
}

class CX implements IFace {
  private string $_propx;

  public string $readable1;
  public string $readable2 {
get => $this->_propx;
set => $this->_propx = $value;
  }

  public function consumeIt(IFace $par) {
// these statements should trigger warning by SA tools
$par->readable1 = "hello";
$par->readable2 = "world";

// OK
$this->readable1 = "hello";

// this statement should trigger error by SA tools
$this->readable2 = "hello";
  }
}
```

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



Re: [PHP-DEV] [RFC] Property hooks, nee accessors

2023-05-15 Thread Hendra Gunawan
> ```php
> class User {
> private string $first;
> private string $last;
> public string $fullName {
> get => $this->first . ' ' . $this->last;
> set => [$this->first, $this->last] = explode(' ', $value, 2);
> }
>
> public function __construct($this->fullName) {}
> }
> ```

Not entirely true, you created redundancy code for ```$fullName```.
This is why we created constructor property promotion: to eliminate
redundancy.

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



Re: [PHP-DEV] [RFC] Property hooks, nee accessors

2023-05-15 Thread Hendra Gunawan
On Tue, May 9, 2023 at 4:38 AM Larry Garfield  wrote:
>
> Ilija Tovilo and I would like to offer another RFC for your consideration.  
> It's been a while in coming, and we've evolved the design quite a bit just in 
> the last week so if you saw an earlier draft of it in the past few months, I 
> would encourage you to read it over again to make sure we're all on the same 
> page.  I'm actually pretty happy with where it ended up, even if it's not the 
> original design.  This approach eliminates several hard-to-implement edge 
> cases while still providing a lot of functionality in one package.
>
> https://wiki.php.net/rfc/property-hooks
>
> --
>   Larry Garfield
>   la...@garfieldtech.com

Hi Larry

Can the engine detect these logical errors?
```
public string $fullName = "hendra gunawan" => $this->first . " " . $this->last;

// or with my proposal:
public string $fullName = "hendra gunawan" get => $this->first . " " .
$this->last;

// or even this one:
public string $fullName = "hendra gunawan" {
  get => $this->first . " " . $this->last;
  set => [$this->first, $this->last] = explode(" ", $value);
```

Explanation:
There is no automatic backing store value created to store the default value.

Terima Kasih.

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



Re: [PHP-DEV] [RFC] Property hooks, nee accessors

2023-05-14 Thread Hendra Gunawan
On Tue, May 9, 2023 at 4:38 AM Larry Garfield  wrote:
>
> Ilija Tovilo and I would like to offer another RFC for your consideration.  
> It's been a while in coming, and we've evolved the design quite a bit just in 
> the last week so if you saw an earlier draft of it in the past few months, I 
> would encourage you to read it over again to make sure we're all on the same 
> page.  I'm actually pretty happy with where it ended up, even if it's not the 
> original design.  This approach eliminates several hard-to-implement edge 
> cases while still providing a lot of functionality in one package.
>
> https://wiki.php.net/rfc/property-hooks
>
> --
>   Larry Garfield
>   la...@garfieldtech.com

Hi, Larry

```
interface IFace
{
  public string $readable { get; }
  public string $writeable { set; }
  public string $both { get; set; }
}
```
How important is ```{ get; }``` statement (and friends) in the interface?

Since PHP does not enforce method definition existence in caller site,
this code is valid (at least at compile time):
```
interface IA {
  // ...
}

interface IB {
  public function doIt(IA $par1);
}

class CA1 implements IA {
  // makeIt is not part of IA
  public function makeIt() {
echo " makeIt() is called";
  }
}

class CA2 implements IA {}

class CB implements IB {
  public function doit(IA $par1) {
// makeIt is not enforced to be invalid
$par1->makeit();
  }
}

$a1 = new CA1;
$a2 = new CA2;
$b = new CB;
$b->doIt($a1); // valid
$b->doIt($a2); // invalid at runtime
```

IMO, ```{ get; }``` (and friends) only useful if there are:
* definition existence enforcement or implemented asymmetric visibility
* AND no default hook implementation provided.

I assume that ```{ get; }``` do exist in the property accessors
proposal because there is no default hook implementation. Whether
there is already implemented property definition existence enforcement
or not, i don't know. If yes, then all things are in the right place.
If not, it feels like a half baked feature, just like the method was:
the error will pop up at runtime. The only positive value is ```{ get;
}``` can still be consumed by static analysis tools.
```
class CX {
  public function consumeIt(IFace $par) {
// this statement should trigger error
// produced by engine or SA tools
$par->readable = "hello";
  }
}
```

Things will be different with property hooks. Without definition
existence enforcement nor implemented asymmetric visibility, static
analysis tools will give misconception about unlisted hooks if there
is error/warning message.
```
class CX {
  public function consumeIt(IFace $par) {
// default hook is provided by engine
// any message is not relevant for this valid statement
$par->readable = "hello";
  }
}
```

If there is no forward compatibility consideration, can we simplify
interface definition to this one?
```
interface IFace
{
  public string $readable;
  public string $writeable;
  public string $both;
}
```

Thanks in advance.

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



Re: [PHP-DEV] [RFC] Property hooks, nee accessors

2023-05-14 Thread Hendra Gunawan
On Tue, May 9, 2023 at 4:38 AM Larry Garfield  wrote:
>
> Ilija Tovilo and I would like to offer another RFC for your consideration.  
> It's been a while in coming, and we've evolved the design quite a bit just in 
> the last week so if you saw an earlier draft of it in the past few months, I 
> would encourage you to read it over again to make sure we're all on the same 
> page.  I'm actually pretty happy with where it ended up, even if it's not the 
> original design.  This approach eliminates several hard-to-implement edge 
> cases while still providing a lot of functionality in one package.
>
> https://wiki.php.net/rfc/property-hooks
>
> --
>   Larry Garfield
>   la...@garfieldtech.com
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>

Hi Larry.

Suppose that I just want to cache once and freeze, and I don't want to
create additional hidden property. Please make a judgement on the
validity of this syntax:
```
public string $prop1 {
  get => $field ??= $this->heavyTask($this->propx, $prop->y);
  set => null;
}
```

Explanation:
* Since the ```get``` hook uses ```$field```, the engine will create a
backing store value with name ```$prop1```, and will be filled at the
first call only. The later call will use the already stored value.
* Since no new value is assigned to ```$field``` in the ```set```
hook, the value stored in ```$prop1``` is still the same as before.
* Since any return statement will be discharged in ```set``` hook, the
assignment chaining is safe to use and the value which is transferred
is alway the rightmost value (not the value returned by the ```set```
hook).
```
$varx = $obj->prop1 = "hello";  // $varx value is "hello", and
$obj->prop1 value is unchanged
```

But, this statement below is NOT ALWAYS correct for "cache once and freeze":
```
public string $prop1 {
  set => $field ??= $this->heavyTask($this->propx, $prop->y);
}
```
Explanation:
* Since default ```get``` hook can be called before ```set``` hook,
backing store value with name ```$prop1``` will still be empty.
* Otherwise, I have to duplicate the body of the ```set``` hook into
```get``` hook to prevent an emptiness backing store.

Please give a comment.
Thanks.

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



Re: [PHP-DEV] [RFC] Property hooks, nee accessors

2023-05-14 Thread Hendra Gunawan
On Tue, May 9, 2023 at 4:38 AM Larry Garfield  wrote:
>
> Ilija Tovilo and I would like to offer another RFC for your consideration.  
> It's been a while in coming, and we've evolved the design quite a bit just in 
> the last week so if you saw an earlier draft of it in the past few months, I 
> would encourage you to read it over again to make sure we're all on the same 
> page.  I'm actually pretty happy with where it ended up, even if it's not the 
> original design.  This approach eliminates several hard-to-implement edge 
> cases while still providing a lot of functionality in one package.
>
> https://wiki.php.net/rfc/property-hooks
>
> --
>   Larry Garfield
>   la...@garfieldtech.com
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>

Hi Larry.

```
public string $fullName => $this->first . " " . $this->last;
```
1. Suppose that I forgot to declare ```$this->first```. Based on the
"deprecate dynamic properties" proposal, will I get an error/warning?

2. The shorthand notations supported (the shortest one) creates
impaired syntax, and not pretty to look at for constructor property
promotion.

```
public function __construct(
  public string $prop1 => strtoupper($this->_prop1),
  public string $prop2 {set => $field = strtolower($value);},
){}
```

My suggestion is: use get/set keyword immediately after property
name/default value rather than "=>" or "{" without losing multiline
statements.
```
public function __construct(
  public string $prop1 get => strtoupper($this->_prop1),
  public string $prop2 set => $field = strtolower($value),
  public string $prop3 get {
$temp = strtoupper($this->_prop1);
return substr($temp, 0, 10) . '...';
  }
  public string $prop4 set {
$temp = strtolower($value);
$field = substr($temp, 0, 10);
  }
){}
```
This syntax is aligned with a single statement if/for/foreach.

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



Re: [PHP-DEV] RFC [Discussion] array_column results grouping

2021-12-07 Thread Hendra Gunawan
>
> And if you want to map, reduce, or filter without grouping? Then you can't
> really use this function. And as noted, the order in which you apply those
> operations may matter, and no order is necessarily more obvious or beneficial

You can modify it slightly if you eager to:

array_group(
...
null|int|string|array $index_key,
...
): array

If You provide `null`, it will operate on a bare array, no grouping involved.
As a consequence, users have to provide `reducer` or `mapper`. So virtually,
You design `array_group` to swallow `array_reduce` and `array_map`. Though,
`array_map` is actually a different API compared to `array_reduce` or
`array_group`.

Interestingly, you will get a better quality of code if you include `reducer: `
and `mapper: ` consistently, whatever array level you work with.

// `array_reduce` and `array_map` alternative
array_group($array, null, reducer: $fnReducer);
array_group($array, null, mapper: $fnMapper);

array_group($array, "level1", reducer: $fnReducer);
array_group($array, "level1", mapper: $fnMapper);
array_group($array, ["level1", "level2"], reducer: $fnReducer);
array_group($array, ["level1", "level2"], mapper: $fnMapper);

I hope there is no bias between the proposed name (`array_group`) and its
functionality.

>
> Either of these approaches would be superior to cramming more functionality
> into a single-purpose function to turn it into a single-function swiss army
> knife:

Not a swiss army knife, just a penknife. AS i wrote before, it is just a
shortcut. If you really mind about that, we can cancel `filter` and `sorter`,
leaving only `reducer` and `mapper`. Thought, we can filtering and sorting
before `array_group`, but i don't know whether it is as accurate as embedding
them into `array_group` or not. If not, we have to iterate manually, do
filtering and/or sorting, then reducing/mapping.

>
> https://wiki.php.net/rfc/comprehensions
> https://wiki.php.net/rfc/pipe-operator-v2

Of course these are wonderful proposals. Yes, they are superior. To be honest,
I really hope they are landed in PHP. I already imagine what part of my code
will be replaced by them. Since I am not a C coder and totally blind about the
engine, I don't have my own opinion whether we lost good things or not, by not
adding them to PHP.

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



Re: [PHP-DEV] RFC [Discussion] array_column results grouping

2021-12-06 Thread Hendra Gunawan
>
> Better map/filter/reduce primitives in PHP would be dandy, but they have
> nothing to do with array grouping. They're a separate operation that should
> be composed with grouping. Packing them all into a single function sounds
> like a terrible idea.
>
> If we wanted that... that's called list comprehensions, which I would
> support and even tried to rally support for a few years ago, but got met
> with a big shrug. :-)

We can imagine that `array_group` is just a shortcut to:

do grouping, and then do reducing. (common to me)

OR:
do filtering, then do grouping, and the last do reducing. (less common to me)

OR:
do sorting, then do filtering, then do grouping, and the last do reducing.

Best Regards
Hendra Gunawan.

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



Re: [PHP-DEV] RFC [Discussion] array_column results grouping

2021-12-06 Thread Hendra Gunawan
>
> Better map/filter/reduce primitives in PHP would be dandy, but they have
> nothing to do with array grouping. They're a separate operation that should
> be composed with grouping. Packing them all into a single function sounds
> like a terrible idea.
>
> If we wanted that... that's called list comprehensions, which I would
> support and even tried to rally support for a few years ago, but got met
> with a big shrug. :-)

`array_group` is just a simple handy tool which can manipulate a bunch of data
without touching SQL, DQL, query builder, or any producer anymore just to align
the output to the need.

Of course we can code with whatever programming paradigm or style we want,
especially if the algorithm is much more complex. Here, i offer you the very
basic functionality and without external library. So my coworker does not have
to dig into that library, or ask me.

The original proposal is to offer grouping, and may be to avoid `foreach`.
I think if the only purpose is to group an array, it is halfly baked function-
ality. Previously, I had shown you that `foreach` is not too bad to use.
Otherwise, I will suggest to the author don't bother with new function, you're
wasting your time. With that original proposed functionality, We have to use an
additional `foreach` or function call even though it is a basic operation.
Moreover, the original purpose is preserved, if we do not give any optional
params.

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



Re: [PHP-DEV] RFC [Discussion] array_column results grouping

2021-12-06 Thread Hendra Gunawan
Revision to my recommendation are:

1. signature:

array_group(
array|object $array,
int|string|array $index_key,
callable $reducer = null,
callable $mapper = null,
callable $filter = null,
callable $sorter = null,
): array

2. `sorter` should be executed before `filter`, because as far as I can think,
   there is no way to do this by yourself. So the sequence should be:
   `sorter` > `filter` > `mapper`|`reducer`

>
> Better map/filter/reduce primitives in PHP would be dandy, but they have
> nothing to do with array grouping. They're a separate operation that should
> be composed with grouping. Packing them all into a single function sounds
> like a terrible idea.
>
> If we wanted that... that's called list comprehensions, which I would
> support and even tried to rally support for a few years ago, but got met
> with a big shrug. :-)


Suppose that my boss order me to provide statistical data of students. He wants
a brief data companied with zoom button on each row. This buttons displays all
fields in which brief data has, plus another zoom button on it's own row. And
so on to some level. Additionally He wants the data not just by area division,
but also by gender as a whole.

// These are reducer
$fnAvg = fn() => {/*...*/}
$fnQ1 = fn() => {/*...*/}
$fnQ2 = fn() => {/*...*/}
$fnQ3 = fn() => {/*...*/}
$fnLowest = fn() => {/*...*/}
$fnHighest = fn() => {/*...*/}

$dAvg = array_group($data, "district", $fnAvg);
$dQ1  = array_group($data, "district", $fnQ1);
$dQ2  = array_group($data, "district", $fnQ2);
// ... and 3 others
$wAvg = array_group($data, ["district", "ward"], $fnAvg);
$wQ1  = array_group($data, ["district", "ward"], $fnQ1);
$wQ2  = array_group($data, ["district", "ward"], $fnQ2);
// ... and 3 others
$cAvg = array_group($data, ["district", "ward", "cluster"], $fnAvg);
$cQ1  = array_group($data, ["district", "ward", "cluster"], $fnQ1);
$cQ2  = array_group($data, ["district", "ward", "cluster"], $fnQ2);
// ... and 3 others
$sAvg = array_group($data, "sex", $fnAvg);
$sQ1  = array_group($data, "sex", $fnQ1);
$sQ2  = array_group($data, "sex", $fnQ2);
// ... and 3 others


output:

$dAvg = [
"district1" => 123,
"district2" => 234,
...
];

$dQ1 = [
"district1" => 123,
"district2" => 234,
...
];

...

$wAvg = [
"district1" => [
"ward1" => 123,
"ward2" => 234,
],
"district2" => [
"ward3" => 123,
"ward4" => 234,
],
...
];

$wQ1 = [
"district1" => [
"ward1" => 123,
"ward2" => 234,
],
"district2" => [
    "ward3" => 123,
"ward4" => 234,
],
...
];

...

$sAvg = [
"female" => 123,
"male" => 234,
...
];
$sQ1 = [
"female" => 123,
"male" => 234,
...
];


`array_group` is just a simple handy tool which can manipulate a bunch of data
without touching SQL, DQL, query builder, or any producer anymore just to align
the output to the need.

Best Regards
Hendra Gunawan.

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



Re: [PHP-DEV] RFC [Discussion] array_column results grouping

2021-12-06 Thread Hendra Gunawan
>
> Hello Folks, Thanks a lot for your feedback, as already mentioned in
> the RFC and as mentioned by Rowan too a new function is an option. I
> think that mostly we will go with the new function option.
> I will try to edit the PR to add a new function, does there any
> suggestions/naming conventions for the new function? a colleague
> suggested being `array_group_by` and Hendra already suggested to be
> `array_column_group` which is good too.

It would be better if You add another voting item for this one. In my opinion,
`column` is less important to be included, and `array_group` is sufficiently
descriptive.

`reducer` is one of the candidates to be included. Additionally, there are
`mapper`, `filter`, and `sorter`. So Obviously we need a new function, rather
than modify the old one.

To be clear and to make it simpler, all callbacks operate on the deepest
subgroup.

Signature:

reducer(array|object $item, int|string $index, mixed $cumulative): mixed
mapper(array|object $item): array|object
filter(array|object $item, int|string $index): bool
sorter(array|object $item1, array|object $item2): int

A note in case you are able to implement them:
- `reducer` and `mapper` cannot coexist in a single function call.
- `filter` should be executed before `reducer` or `mapper`.
- `sorter` should be decided whether it executes before or after `reducer`/
  `mapper`: `sorter` is more suitable to execute before `filter`, but more
   suitable after `mapper`.

A note for consumers:
- `mapper` is designed to operate on the subgroup item, but it can be operated
  on the field value of the item.
- filtering can be done inside `reducer` or `mapper`, but the number of
  subgroup members is as it is. With dedicated `filter` supplied, we can
  decrease the number.
- If You want to filter an intermediate group, You can use `unset` or `if-else`


$group = array_group($people, ["education", "sex"], FN_REDUCER);
foreach ($group as &$eduGroup) {
foreach ($eduGroup as &$sexGroup) {
unset($sexGroup["male"]);
}
}

Not a perfect solution, but at least your code is reduced.

Best Regards
Hendra Gunawan.

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



Re: [PHP-DEV] RFC [Discussion] array_column results grouping

2021-12-04 Thread Hendra Gunawan
>
> Hello, this is a proposal to upgrade the functionality of
> `array_column` to return an indexed array for all of the matched data
> instead of a single result.
>
> the RFC had been created here
> https://wiki.php.net/rfc/array_column_results_grouping and the PR is
> in here https://github.com/php/php-src/pull/7698.
>
> However, I am not sure, if we need to add a fourth parameter to the
> function to change its behavior or we can add it as a new function,
> something like `array_column_group` or any other name.
>

Hai Hassan.

It seems that your proposal is just save no more than 3 lines compared with
`foreach`. Moreover, `foreach` can do better than your version.

foreach ($persons as $p) {
$groups[$p["education"]][$p["sex"]][MORE_SUBGRUP][] = $p;
}


output:

$groups = [
"elementary" => [
"female" => [
MORE_SUBGRUP_1 => [
0 => [...],
1 => [...]
],
MORE_SUBGRUP_2 => [
0 => [...],
1 => [...]
],
...
],
"male" => [
MORE_SUBGRUP_1 => [
0 => [...],
1 => [...]
],
MORE_SUBGRUP_2 => [
0 => [...],
1 => [...]
],
...
],
],
"highschool" => [
...
],
...
];

my suggestions are:
- don't limit to array => involve object as well
- offer reducer callable as an optional last param.

reducer callable it will transform 2 steps algo (populating the groups and then
reducing) to become a single step. but if it is not provided, the function
returns the member of the group (same as example above).


old way:

// step-1
$group = [];
foreach ($persons as $p) {/*...*/}

// step-2
foreach ($group as &$eduGroup) {
foreach ($eduGroup as &$sexGroup) {
$sumWeight = 0;
foreach ($sexGroup as $item) {
$sumWeight += $item->weight;
}
$sexGroup = $sumWeight / count($sexGroup);
}
}

output:

$groups = [
"elementary" => [
"female" => 40,
"male" => 50,
],
"highschool" => [
"female" => 60,
"male" => 65,
],
...
];

new way:

array_column_group(
$group,
["education", "sex", MORE_SUBGRUP],
fn ($item, $i, $cumm) => ($item->weight + ($cumm * $i)) / ($i + 1)
);


the signature:

// array_column_group signature
array_column_group(
array|object $array,
int|string|array $index_key,
callable $reducer = null
)

// callable signature
fn (array|object $item, int|string $index, mixed $cummulative): mixed

note:
- $index_key can be in the form `["education", ...]` or `"education"`.
- or even `[0, 1, ...]` or `0`.

So virtually, `array_column_group` is a hybrid between `array_column` and
`array_walk` (or other function with a funny name which I don't remember).

Best Regards
Hendra Gunawan.

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



Re: [PHP-DEV] [RFC] Deprecate dynamic properties

2021-08-25 Thread Hendra Gunawan
Hi.

A chunk in the RFC:

abstract class Constraint {
public $groups;

public function __construct() {
unset($this->groups);
}

public function __get($name) {
// Will get called on first access, but once initialized.
$this->groups = ...;
}
}

Interesting! new to me.

Maybe someday we will have this one:

abstract class Constraint {
public lazy $groups;

public function __construct() {
// no need to do this:
// unset($this->groups);
}

public function __get($name) {
// Will get called on first access, but once initialized.
$this->groups = ...;
}
}

Regards,
Hendra Gunawan.

-- 
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-28 Thread Hendra Gunawan
Hello.

>
> The only correct way to resolve this issue is to not support mutable 
> operations.
>

Correct me if I'm wrong: scalar object will hit memory limit earlier
than old API if it applied to $some_huge_shared_array for several
method calls.

>
> I don't think there's much need for mutable operations. sort() and shuffle() 
> would be best implemented by returning a new array instead. array_push() is 
> redundant with $array[]. array_shift() and array_unshift() should never be 
> used. array_pop() and array_splice() are the only sensible mutable array 
> methods that come to mind, and I daresay we can do without them.
>

Suppose that we all agree with that. **Will scalar object preserve
most of all functionality of the old API?** Some functions are very
handy that keep us away from the gory detail implementation. In array
case, we know that PHP array is a combination of array and plain
object in JS term. There is a trend in user land PHP library that they
are just copying the JS array API and poorly preserving the existing
functionality of PHP old API. Implicitly, the author of this thread
wants this to happen.

If I am not wrong, scalar object date back to before PHP 7.0. Is there
any consideration why scalar object was not escalated to the next
phase, say to RFC?

Regards
Hendra Gunawan.

--
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-26 Thread Hendra Gunawan
Hello.

>
> Yes, but Nikita wrote this note about technical limitations at the bottom of 
> the repo README:
>
> Due to technical limitations, it is not possible to create mutable APIs for
> primitive types. Modifying $self within the methods is not possible (or
> rather, will have no effect, as you'd just be changing a copy).
>

If it is solved, this is a great accomplishment for PHP. But I think
scalar object is not going anywhere in the near future. If you are not
convinced, please take a look
https://github.com/nikic/scalar_objects/issues/20#issuecomment-569520181.

This makes me have a strong feeling about pipe operator greater than
before to solve object-style for scalar issue.

I hope that someone will take an initiative to fix the old
inconsistent and confusing API.

Pipe operator+new API is a better solution than no solution at all.

-- 
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 Hendra Gunawan
Hello.

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

Whitespace removal is not a solution for code length problems.
You might have a new problem if you do it. "|" is very similar
to the lowercase "L" and uppercase "i".

It's just an extra 3 characters (", ?" or "?, "). For most people,
this is not a problem at all. people tend to write "one statement per line"
rather than "multi statement line". I myself usually write no more than
3 statements per line if they are less than 120 characters.

The real problem is there is no consistency for "haystack vs needle"
position. There are RFCs to fix this (along with the naming convention
problem), but none of them are successful.

> The pipe operator feels like a poor solution while "->" would do
> exactly what people want.

Not so poor if we
* use "~>" as pipe operator rather than "|>"
* redesign the api under their proper namespace and strictly place
  the "haystack" as the first function argument.

Regards,
Hendra Gunawan.

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



Re: [PHP-DEV] [RFC] Property accessors

2021-05-16 Thread Hendra Gunawan
Hi internals,
>
> I'd like to present an RFC for property accessors:
>
> https://wiki.php.net/rfc/property_accessors


Hi internals,

I am new here.

Thank you Nikita for this wonderful proposal.

A few days ago, I sent an identical message to this thread but I am not
sure it was sent properly. So I sent it back here. Sorry about this.

Let me make a suggestion for this one of mostly asked feature:

class  MyOldOrdinaryObject {
public string $prop1 { get use getProp1; set use setProp1; }
public string $prop2 { get use prefixProp2; set use prop2Sufix; }

// pre existing methods
// same function signature with corresponding accessor
// method name is irrelevant
public function getProp1(): string {/* ... */}
public function setProp1(string $val): void {/* ... */}
public function prefixProp2(): string {/* ... */}
public function prop2Sufix(string $val): void {/* ... */}
}

This way:
* without forcing them to use the new ones, users can choose whether to use
old ones or new ones.
* code duplication can be prevented, if we decided to preserve the old ones.
* the accessors are more tidy and readable, if we decided to move out all
multiline accessors.

As far as I understand, the difference between "set" and "guard" is: with
"set", we have freedom and responsibility to allocate a space.
Additionally, we have to choose whether to use "set" or "guard", not both.

It is a sad decision that "guard" has to be eliminated to reduce
complexity. In my opinion, it is valuable that we can write code more
concise than before:

class  MyOldOrdinaryObject {
public string $prop1 { get; guard use commonGuard; }
public string $prop2 { get; guard use commonGuard; }

// Assuming that prop1 & prop2 have the same validity rules.
// The visibility is private in order to prevent users accessing it.
// Due to loss of space allocation and difference of function
// signature, this method cannot be used in concert with "set".
private function commonGuard(): void {/* ... */}
}

With this capability, the complex accessor in constructor problem can be
solved

class MyValueObject {
public function __construct(
public string $prop1 { get; private guard use guard1; }
public string $prop2 { get; private guard use guard2; }
public string $prop3 { get; private guard use commonGuard; }
public string $prop4 { get; private guard use commonGuard; }
){}

private function guard1(): void {/* ... */}
private function guard2(): void {/* ... */}
private function commonGuard(): void {/* ... */}
}

I hope that "guard" can be included again.

I don't understand the internals of the engine. I think the mechanism of
this is compiler assisted copy-paste (same as traits), but only the
function body and the visibility is overridden based on accessors
definition.

Regards,
Hendra Gunawan.


Re: [PHP-DEV] [RFC] Property accessors

2021-05-07 Thread Hendra Gunawan
 Hi internals,

I am new here.

Let me make a suggestion for this one of mostly asked feature:

class  MyOldOrdinaryObject {
public string $prop1 { get use getProp1; set use setProp1; }
public string $prop2 { get use prefixProp2; set use prop2Sufix; }

// pre existing methods
// same function signature with corresponding accessor
// method name is irrelevant
public function getProp1(): string {/* ... */}
public function setProp1(string $val): void {/* ... */}
public function prefixProp2(): string {/* ... */}
public function prop2Sufix(string $val): void {/* ... */}
}

This way:
* without forcing them to use the new ones, users can choose whether to use
old ones or new ones.
* code duplication can be prevented, if we decided to preserve the old ones.
* the accessors are more tidy and readable, if we decided to move out all
multiline accessors.

As far as I understand, the difference between "set" and "guard" is: with
"set", we have freedom and responsibility to allocate a space.
Additionally, we have to choose whether to use "set" or "guard", not both.

It is a sad decision that "guard" has to be eliminated to reduce
complexity. In my opinion, it is valuable that we can write code more
concise than before:

class  MyOldOrdinaryObject {
public string $prop1 { get; guard use commonGuard; }
public string $prop2 { get; guard use commonGuard; }

// Assuming that prop1 & prop2 have the same validity rules.
// The visibility is private in order to prevent users accessing it.
// Due to loss of space allocation and difference of function
signature,
// this method cannot be used in concert with "set".
private function commonGuard(): void {/* ... */}
}

With this capability, the complex accessor in constructor problem can be
solved:

class MyValueObject {
public function __construct(
public string $prop1 { get; private guard use guard1; }
public string $prop2 { get; private guard use guard2; }
public string $prop3 { get; private guard use commonGuard; }
public string $prop4 { get; private guard use commonGuard; }
){}

private function guard1(): void {/* ... */}
private function guard2(): void {/* ... */}
private function commonGuard(): void {/* ... */}
}

I hope that "guard" can be included again.

I don't understand the internals of PHP VM. I think the mechanism of this
is compiler assisted copy-paste (same as traits), but only the function
body and the visibility is overridden based on accessors definition.

Regards,
Hendra Gunawan.


On Sat, May 8, 2021 at 5:16 AM Larry Garfield 
wrote:

> On Tue, May 4, 2021, at 5:33 AM, Nikita Popov wrote:
> > Hi internals,
> >
> > I'd like to present an RFC for property accessors:
> > https://wiki.php.net/rfc/property_accessors
> >
> > Property accessors are like __get() and __set(), but for a single
> property.
> > They also support read-only properties and properties with asymmetric
> > visibility (public read, private write) as a side-effect.
> >
> > The proposal is modeled after C#-style accessors (also used by Swift),
> and
> > syntactically similar to the previous
> > https://wiki.php.net/rfc/propertygetsetsyntax-v1.2 proposal.
> >
> > While I put a lot of effort into both the proposal and the
> implementation,
> > I've grown increasingly uncertain that this is the right direction for us
> > to take. The proposal turned out to be significantly more complex than I
> > originally anticipated (despite reducing the scope to only "get" and
> "set"
> > accessors), and I'm sure there are some interactions I still haven't
> > accounted for. I'm not convinced the value justifies the complexity.
> >
> > So, while I'm putting this up for discussion, it may be that I will not
> > pursue landing it. I think a lot of the practical value of this accessors
> > proposal would be captured by support for read-only (and/or
> private-write)
> > properties. This has been discussed (and declined) in the past, but
> > probably should be revisited.
> >
> > Regards,
> > Nikita
>
> Another question: I skimmed through the PR and its tests, and I didn't see
> any tests around attributes.
>
> How do you envision attributes interacting with accessor-using
> properties?  I suppose there's no change for implicit accessors, but what
> happens for explicit accessors?
>
> --Larry Garfield
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>
>