Re: [PHP-DEV] PHP 8 is_file/is_dir input handling

2020-12-09 Thread Mike Schinkel


> On Dec 8, 2020, at 11:27 AM, Christian Schneider  
> wrote:
> 
> Am 08.12.2020 um 17:16 schrieb Mike Schinkel  >:
>> 1. Please consider making is_file() return false for an embedded \0 and no 
>> longer throw an exception or generate a warning.
> 
> The PR implementing this has already been merged for inclusion in PHP 8.0.1: 
> https://github.com/php/php-src/pull/6478 
> 
Thanks.

> 
>> 2. Beyond is_file(), please consider allowing PHP to support both types of 
>> error handling strategies without forcing complexity just to use the 2nd 
>> strategy.
> 
> 
> This is a contentious topic

Exactly.

> and will have to be handled on a case by case basis I guess.

Which is really all I was asking for; that it be considered on a case-by-case 
basis instead of just assuming that exceptions are always preferable.


> E.g. for security-related stuff a fail-early-strategy throwing an exception 
> might be preferable, for basic lower-level functions like is_file() returning 
> false was chosen to be preferable.
> There is no silver bullet for all cases and having a global switch would only 
> make things worse.

-Mike

Re: [PHP-DEV] [RFC] Enumerations

2020-12-09 Thread Mike Schinkel
> On Dec 4, 2020, at 6:24 PM, Larry Garfield  wrote:
> 
> Greetings, denizens of Internals!
> 
> Ilija Tovilo and I have been working for the last few months on adding 
> support for enumerations and algebraic data types to PHP.  This is a 
> not-small task, so we've broken it up into several stages.  The first stage, 
> unit enumerations, are just about ready for public review and discussion.
> 
> The overarching plan (for context, NOT the thing to comment on right now) is 
> here: https://wiki.php.net/rfc/adts
> 
> The first step, for unit enumerations, is here:
> 
> https://wiki.php.net/rfc/enumerations

Great work.

> 
> There's still a few bits we're sorting out and the implementation is mostly 
> done, but not 100% complete.  Still, it's far enough along to start a 
> discussion on and get broader feedback on the outstanding nits.

1. Will enum methods be idempotent?  

If not, shouldn't they be?

-

2. Will enum cases be able to have attributes applied given the change in 
implementation?

-

3. "Cases are not intrinsically backed by a scalar value."

Completely agree with not using an ordinal value. It is too easy to change an 
ordinal value and break some hidden dependency.

However, I would ask we consider a default string value, i.e. that this:

enum Size {
case Small;
case Medium;
case Large;
} 

Would be equivalent to:

enum Size {
case Small = 'Small';
case Medium = 'Medium';
case Large = 'Large';
} 

The justification is for use-cases with a large number of cases it would be too 
easy to have typos and/or copy-paste errors if the developer has to explicitly 
specify the value.

Also, the following would leave the values of Medium and Large undefined given 
that enumerations supports only a single type at a time:

enum Size {
case Small = 1;
case Medium;
case Large;
} 

So, can enums get a default value of their name as a string when zero values 
are provided?

-

4. "Class/Enum inheritance. - Enums are by design a closed list"

I would ask if this is really necessary to disable inheritance? 

Consider the following as a example where I use a known list for clarity but 
where I am really more interested is lists a developer maintains, i.e. their 
own apps list of errors:

enum OsErrors {
   case EPERM = 1;
   case EINTR = 4;
   case EIO = 5;
   case ENXIO = 6;
   case E2BIG = 7;
   
} 

enum FileErrors extends OsErrors {
   case ENOENT = 2;
   case ENOEXEC = 8;
   case EBADF = 9;
   
} 

enum ProcessErrors extends OsErrors {
   case ESRCH = 3;
   case ECHILD = 10;
   
} 

Without inheritance a developer could not create a new error enum, such as 
SpeachRecognitionErrors and be able to include the base errors without having 
to duplicate them.

Now it is very possible that someone can focus on my example and explain why 
enums are not the right solution here, but please do not to that.  

Instead please consider without inheritance nobody would be able to reuse a 
base set of enums w/o duplication of names and/or values. 

So can we revisit the idea of disallowing inheritance?

-

5. Someone else mentioned shortcut syntax, which I would like to mention again, 
although I realize implement details might make this a non-starter.  

So if I have a function that accepts a Size from above, e.g.:

function show(Size $size) {}

Then it would be great if we could call the function like this since its 
parameter was type-hinted:

show(::Medium) 

Rather than always having to write:

show(Size::Medium) 

So can we consider a shortcut syntax?

-


> I should note that while the design has been collaborative, credit for the 
> implementation goes entirely to Ilija.  Blame for any typos in the RFC itself 
> go entirely to me.
> 
> *dons flame-retardant suit*
> 
> -- 
>  Larry Garfield
>  la...@garfieldtech.com
> 
> -- 
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
> 

Again, great work!

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



Re: [PHP-DEV] [RFC] Enumerations

2020-12-09 Thread Rowan Tommins

On 09/12/2020 18:47, Mike Schinkel wrote:

1. Will enum methods be idempotent?

If not, shouldn't they be?



Can you clarify what you mean here? The only meaningful question I can 
think of is "can they change the object's state?" That's mostly answered 
in the RFC, most notably by specifying that enums may not have instance 
properties, to avoid them having any state to change.


Unless I'm missing something, trying to define "idempotence" or "pure 
functions" any more strictly than that would surely be a massive project 
in itself - for a start, you'd need a whitelist of all built-in 
operations which were side-effect free (i.e. no file writes, 
configuration changes, output, etc, etc).


Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

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



Re: [PHP-DEV] [RFC] Enumerations

2020-12-09 Thread Mike Schinkel
> On Dec 9, 2020, at 2:06 PM, Rowan Tommins  wrote:
> 
> On 09/12/2020 18:47, Mike Schinkel wrote:
>> 1. Will enum methods be idempotent?
>> 
>> If not, shouldn't they be?
> 
> 
> Can you clarify what you mean here?

For a given parameter set the method would always return the same value. Note I 
am not suggesting that values would be fixed across different executions, only 
within a given execution.

Said another way, idempotent and deterministic[1] are effectively equivalent.

Taking this example the now() method would not be idempotent nor deterministic:

enum DayParts {  
case Morning;
case Afternoon;
case Evening;
case Night;
public static function now() {
$now = intval(date('H',time()));
return match(true) {
$now < 8 => static::Night,
$now < 12 => static::Morning,
$now < 18 => static::Afternoon,
default => static::Evening,
};
}
}

[1] 
https://docs.microsoft.com/en-us/sql/relational-databases/user-defined-functions/deterministic-and-nondeterministic-functions

> The only meaningful question I can think of is "can they change the object's 
> state?" That's mostly answered in the RFC, most notably by specifying that 
> enums may not have instance properties, to avoid them having any state to 
> change.
> 
> Unless I'm missing something, trying to define "idempotence" or "pure 
> functions" any more strictly than that would surely be a massive project in 
> itself - for a start, you'd need a whitelist of all built-in operations which 
> were side-effect free (i.e. no file writes, configuration changes, output, 
> etc, etc).

I do not believe it should be a massive project. I believe it could be 
implemented with a simple map that takes a hash of the input parameters and 
maps to their return value.  For idempotency this value should be calculated 
the first time the method is called. 

After the first call every subsequent call would hash the input parameters, 
lookup the pre-calculated value from the map, and the just return it without 
re-executing any code in the method except for the return statement (I am 
considering of the desire to set a breakpoint in XDEBUG on return for all 
accesses, not just the first.)

The one potential concern is if the number of potential input permutations is 
large it could eat a lot of memory if the app actually used a lot of them.  But 
then that is true on any use of memory in PHP, so if it became a problem for a 
developer I think it should be on them to rearchitect their solution to avoid 
using too much memory.

This is an important question to answer *now* because IF the answer to 
idempotency  is "no" then restricting it a later to be idempotent would require 
accepting a BC break.  But if the answer is YES, the restriction could always 
be relaxed in a future version if that ever made sense.

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



Re: [PHP-DEV] [RFC] Enumerations

2020-12-09 Thread Benjamin Morel
On Wed, 9 Dec 2020 at 19:48, Mike Schinkel  wrote:

5. Someone else mentioned shortcut syntax, which I would like to mention
> again, although I realize implement details might make this a non-starter.
>
> So if I have a function that accepts a Size from above, e.g.:
>
> function show(Size $size) {}
>
> Then it would be great if we could call the function like this since its
> parameter was type-hinted:
>
> show(::Medium)
>
> Rather than always having to write:
>
> show(Size::Medium)
>
> So can we consider a shortcut syntax?
>

I'm not sure what value a shortcut syntax would bring, but it would surely
break, or at least make ambiguous, union types:

function show(Enum1|Enum2 $value)  {}
show(::Medium)

Which enum would Medium resolve to?

- Benjamin


Re: [PHP-DEV] [RFC] Enumerations

2020-12-09 Thread Mike Schinkel
> On Dec 9, 2020, at 3:29 PM, Benjamin Morel  wrote:
> 
> On Wed, 9 Dec 2020 at 19:48, Mike Schinkel  > wrote:
> 
> 5. Someone else mentioned shortcut syntax, which I would like to mention 
> again, although I realize implement details might make this a non-starter.  
> 
> So if I have a function that accepts a Size from above, e.g.:
> 
> function show(Size $size) {}
> 
> Then it would be great if we could call the function like this since its 
> parameter was type-hinted:
> 
> show(::Medium) 
> 
> Rather than always having to write:
> 
> show(Size::Medium) 
> 
> So can we consider a shortcut syntax?
> 
> I'm not sure what value a shortcut syntax would bring, but it would surely 
> break, or at least make ambiguous, union types:
> 
> function show(Enum1|Enum2 $value)  {}
> show(::Medium)
> 
> Which enum would Medium resolve to?

Good question.  

What *could* happen is:

1. It could resolve to the Enum that has a ::Medium, 

2. Or it could be disallowed for union type hints (probably the better option 
as adding a "Medium" to the other enum could inadvertently break code that 
calls it.)

3. This suggestion could just be tabled.


Again, I am just asking if this is something we could consider because it would 
be nice to shorten line length in cases where expressions get really long.


Maybe a different question could be if a "use" statement could empower making 
explicit shorthands/aliases?


-Mike

P.S. I completely understand if either of these things are out of scope for 
this RFC.



Re: [PHP-DEV] [RFC] Enumerations

2020-12-09 Thread Larry Garfield
On Wed, Dec 9, 2020, at 2:03 PM, Mike Schinkel wrote:


> > Unless I'm missing something, trying to define "idempotence" or "pure 
> > functions" any more strictly than that would surely be a massive project in 
> > itself - for a start, you'd need a whitelist of all built-in operations 
> > which were side-effect free (i.e. no file writes, configuration changes, 
> > output, etc, etc).
> 
> I do not believe it should be a massive project. I believe it could be 
> implemented with a simple map that takes a hash of the input parameters 
> and maps to their return value.  For idempotency this value should be 
> calculated the first time the method is called. 
> 
> After the first call every subsequent call would hash the input 
> parameters, lookup the pre-calculated value from the map, and the just 
> return it without re-executing any code in the method except for the 
> return statement (I am considering of the desire to set a breakpoint in 
> XDEBUG on return for all accesses, not just the first.)
> 
> The one potential concern is if the number of potential input 
> permutations is large it could eat a lot of memory if the app actually 
> used a lot of them.  But then that is true on any use of memory in PHP, 
> so if it became a problem for a developer I think it should be on them 
> to rearchitect their solution to avoid using too much memory.
> 
> This is an important question to answer *now* because IF the answer to 
> idempotency  is "no" then restricting it a later to be idempotent would 
> require accepting a BC break.  But if the answer is YES, the 
> restriction could always be relaxed in a future version if that ever 
> made sense.
> 
> -Mike

What you're describing is memoization.  Memoization is only safe on idempotent 
functions.  Please do not confuse the two terms, as they mean very different 
things.

However, as long as global variables exist in the language and there are file 
IO operations defined, we cannot guarantee that a given method is idempotent 
and thus safely memoizable.  Saying "well this function/method really should be 
idempotent if you're doing it right" (even when correct) is insufficient 
justification for blindly memoizing it.  That's true regardless of whether or 
not the method in question is on an enum.

Having a way for developers to flag a function as safe to memoize would be 
helpful, but is a completely different topic from Enums.

Forbidding enum-bound state is as close to guaranteed idempotence as PHP 
allows, which is what the current RFC does.

--Larry Garfield

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



Re: [PHP-DEV] [RFC] Enumerations

2020-12-09 Thread Lester Caine

On 04/12/2020 23:24, Larry Garfield wrote:

The first step, for unit enumerations, is here:
https://wiki.php.net/rfc/enumerations
There's still a few bits we're sorting out and the implementation is mostly 
done, but not 100% complete.


I use 'Enumerations' quite extensively but have not found the lack of a 
hard coded base for that a limitation at least partially because as 
provided in databases the fundamental restrictions that imposes make 
using them something of a 'bodge job'.


There are two areas I would highlight as causing problems. ...

1/ Dynamic Enumerations ... where the application may need to add or 
delete values over time. I have a number of tables in the database which 
provide a dynamic list of elements which are used to provide the lists 
inside the PHP functionality. These are invariably managed by a numeric 
index in addition to the text of each item, and historic values remain 
in the database flagged as inactive.


2/ An area that PHP remains poor at supporting, internationalization. 
Since the vast number of end users do not have English as a first 
language, then translations of the enumeration values becomes essential 
and the table approach obviously works nicely here since one simply 
provides multiple sets of text in parallel and select the language 
needed as an option.


I am not saying that there is anything wrong with the proposal, only 
that as with many aspects being proposed these days, there is a distinct 
lack of consideration on just how some aspects of their use can be 
expanded to cover internationalization and the example in the RFC has no 
obvious way of supporting a different language?


--
Lester Caine - G8HFL
-
Contact - https://lsces.uk/wiki/Contact
L.S.Caine Electronic Services - https://lsces.uk
Model Engineers Digital Workshop - https://medw.uk
Rainbow Digital Media - https://rainbowdigitalmedia.uk

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