Re: [PHP-DEV] Autoloading functions/consts without a performance impact

2020-01-06 Thread Rasmus Schultz
On Sun, Jan 5, 2020 at 7:48 PM Rowan Tommins 
wrote:

> On 05/01/2020 18:03, tyson andre wrote:
> >> Yes, I'm saying that the autoloader should be called for each lookup, so
> >> autoloading of Foo\strlen should come between checking if Foo\strlen is
> >> defined, and checking if \strlen is defined.
> > That would be the intuitive approach for a language,
> > but as mentioned earlier,
> > it would significantly harm performance of existing code for php 7
> > (slightly without an autoloader, more with autoloaders),
> > and I can't imagine that getting approved.
>
>
> Yes, I'm fully aware of the downsides. I just think relaxing that
> constraint would lead to a horribly confusing language.
>
>
> > I'd considered that option, but that introduces its own surprises,
> > which I'd consider to have more frequent and significant impact on
> applications that start using this.
> >
> > namespace NS;
> > function f1($x) {
> >   return mb_strlen($x) + 1;
> > }
> > function f2($x) {
> >   return \mb_strlen($x) * 2;
> > }
> >
> > Calling f2() then f1() would work, but f1() then f2() would not work,
> because f1() wouldn't autoload.
>
>
> True; again, it violates the user's expectation, which I think can be
> summed up this way:
>
> - The autoloader for a function should run the first time that function
> would run if it was pre-defined.
>
> That in turn stems from an even more fundamental expectation:
>
> - An application using an autoloader should behave the same as one which
> defines all functions in advance.
>
>
> The more I think about it, the more I think we should just be optimising
> for the case where everything *is* defined in advance. As far as I know,
> PHP's autoloading is an anomaly among programming languages, and maybe
> it has outlived its usefulness.
>

I would argue that name resolution, the way it works right now, is also
somewhat of an anomaly among programming languages.

Removing autoloading from the language would have two major implications:

1. You have to figure out what to load in advance - thinking you can just
preload all *.php files in a folder is probably pretty naive, because some
of those files (PHP being a scripting language) are going to be actual be
scripts (CLI scripts, tests, etc.) and not just declarations.

2. Code generation - and I mean, think of that what you want, but PHP lends
itself well to code generation, and many projects (ORMs, template engines,
annotation parsers, AOP and other meta-programming frameworks, etc.) use
the autoloader as a hook to generate code on the fly.

So this seems like a fairly drastic change to the language, which might
render a lot of projects defunct with no recourse.


Re: [PHP-DEV] Autoloading functions/consts without a performance impact

2020-01-03 Thread Rasmus Schultz
On Fri, Jan 3, 2020 at 10:35 AM Nikita Popov  wrote:

> On Fri, Jan 3, 2020 at 2:51 AM tyson andre 
> wrote:
>
> > After a quick search, it turns out I've mostly reinvented
> > https://wiki.php.net/rfc/autofunc which I hadn't remembered.
> > The `spl_autoload_*()` changes it mentions is what I had in mind
> >
> > There's been changes to php since then, it's been 7 years,
> > and this adds thoughts on some implementation details.
> >
> > It's possible to support function / const autoloading
> > in a way that keeps existing performance.
> > Some of the objections at the time no longer apply.
> >
> > - `SOME_CONSTANT` no longer falls back to the literal string in php 8.
> >   It throws an Error.
> > - APC (used by some implementations) is no longer supported.
> > - Many of the objections were against the available implementations
> >   based on `function __autoload()`, not the concept of autoloading.
> >
> >   https://www.mail-archive.com/internals@lists.php.net/msg52307.html
> > - There wasn't much traction from leads for the concept
> >   or a Proof of Concept to vote on for that RFC (I think).
> >
> > What if an ambiguous `function_name()` or const outside the global
> > namespace would attempt to autoload functions in the global namespace
> > if it would throw an Error, but not the current namespace?
> >
> > `function_exists()` or `defined()` would not autoload,
> > to preserve the behavior/performance of current programs.
> > Anything with the callable type hint (e.g. `array_map`) would also need
> to
> > be modified,
> > but I think it already needs to do that for method arrays and
> > 'MyClass::method'.
> >
> > - Same for global constants
> > - That should avoid the performance hit - this autoloading would only be
> > triggered
> >   when php would previously throw an Error or warning
> >   for undefined functions/constants.
> > - This would also avoid the need to load polyfill files (e.g. mbstring)
> >   or test framework files when their functions/constants are unused.
> > - One blocker for other autoload proposals
> >   seemed to be performance if I understood correctly
> >   (e.g. attempting to autoload NS\strlen() every time strlen was called).
> >
> >   https://externals.io/message/54425#54616 and
> > https://externals.io/message/54425#54655
> >   detail this - choosing a different order of checks avoids the
> > performance hit.
> > - In addition to the RFC, changing the signatures to `defined(string
> > $name, bool $autoload = false)`
> >   and `function_exists($name, bool $autoload = false)`
> >   might be useful ways to allow users to choose to autoload when checking
> > for existence.
> >
> > And there'd have to be a hash map, flag, or other check
> > to avoid recursion on the same constant/function.
> >
> > Background: A function call or constant usage is
> > ambiguous if it could look for the function in two namespaces,
> > as described by the rules documented in the below link.
> > It's unambiguous if it ends up looking in only one namespace.
> >
> > https://www.php.net/manual/en/language.namespaces.rules.php
> > The only type of ambiguous function call or global constant use is (7.):
> >
> > > 7. For unqualified names,
> > >if no import rule applies and the name refers to a function or
> > constant
> > >and the code is outside the global namespace, the name is resolved
> at
> > runtime.
> > >Assuming the code is in namespace A\B, here is how a call to
> function
> > foo() is resolved:
> > >1. It looks for a function from the current namespace: A\B\foo().
> > >2. It tries to find and call the global function foo().
> >
> > My approach should be in line with the current name resolution
> > for unqualified names outside the global namespace.
> >
> > 1. It (first) looks for a function from the current namespace: A\B\foo().
> > 2. It (next) tries to find and call the global function foo().
> > 3. (Optional) NEW ADDITION: Next, if both functions were undefined,
> >the autoloader(s) attempt to autoload the function A\B\foo()
> >(and call it instead of throwing if found) before proceeding to step
> > (4.)
> > 4. NEW ADDITION: If both functions were undefined,
> >the autoloader(s) attempt to autoload the global function foo()
> >(and call it instead of throwing if found) before throwing an Error
> >
> > And for unambiguous calls, find and autoload the only name it has.
> >
> > The fact that one of the two possible functions gets cached by the php VM
> > in CACHED_PTR
> > (for the lifetime of the request) the first time the function is found
> > in either namespace will remain unchanged with this proposal.
> >
>
> I believe the problem here is this: The fact that the global function is
> being cached, and continues to be cached when a namespaced function is
> later defined, is a bug. See for example
> https://bugs.php.net/bug.php?id=64346. We've never prioritized fixing this
> issue, but implementing the proposed autoloading behavior would make fixing
> it 

Re: [PHP-DEV] [RFC] Object Initializer

2019-09-13 Thread Rasmus Schultz
I'd like to address the examples - and why I think they don't demonstrate
that this feature is really useful in practice.

There are several examples similar to this one:

class Car
{
  public int $yearOfProduction;
  public string $vin;
}

This is either lacking a constructor to initialize the properties to the
defined types - or it's lacking nullable type-hints. As it is, this class
doesn't guarantee initialization according to it's own property type
constraints.

Assuming the fields of this entity are required, you would probably prefer
to add a constructor - but then property initializers aren't really useful
anymore. This seems to be the case for most of the examples.

Models often have other constraints besides just the type - in those cases,
your models would likely have private/protected fields and setter-methods
that implement those constraints. The visibility example demonstrates the
use of a static factory method:

class Customer
{
  private string $name = '';
  protected ?string $email = null;

  public static function create(string $name, ?string $email = null): self
  {
return new self {
  name = $name, // assign private property within the same class
  email = $email, // assign protected property within the same class
};
  }
}

This may be fine for some use-cases - but many model types are only going
to have one valid way to construct an instance, and constructors are the
idiomatic way to do that. Unfortunately, this language feature works for
the new-statement only, so a desire to use this language feature will drive
architecture.

All in all, I find this feature is useful or applicable only to a few,
select patterns within the language - it isn't general enough.

In my opinion, language features should be as general as possible - a
feature like this "looks nice", being very abbreviated and clean-looking,
and, as I believe the examples in the RFC itself demonstrates, this will
provide the wrong kind of motivation to make what are, effectively,
architectural decisions.

Some models are immutable by design. Those cases don't seem to be well
supported by this feature.

My strong preference over this feature would be named parameters, which can
provide the same abbreviated initializations, but works more consistently
with the language, e.g. for all of the use-cases I cited above.

It works for constructors:

class Car
{
  public int $yearOfProduction;
  public string $vin;

  public function __construct(int $yearOfProduction, string $vin) {
if ($yearOfProduction < 1900 ||  $yearOfProduction > date("Y")) {
  throw new InvalidArgumentException("year of production out of range:
{$yearOfProduction}");
}

$this->yearOfProduction = $yearOfProduction;
$this->vin = $vin;
  }
}

$car = new Car({ yearOfProduction = 1975, vin = "12345678"});

It works for static factory-methods:

$car = Car::create({ yearOfProduction = 1975, vin = "12345678"});

It works for models with private/protected fields, classes with accessors,
classes with validations in constructors or factory-methods, and so on.

In other words, it works more generally with all common patterns and
practices - in many ways, it just seems like a better fit for the language.

The common criticism against named parameters, is they create coupling to
parameter-names. Object initializers create coupling to property-names - if
you can live with that, I don't think named parameters or object
initializers are very different in that regard.

The only problem I see with named parameters as an alternative to object
initializers, is in terms of versioning - renaming an argument, today, is
not a breaking change, and now it would be. That could be addressed, for
example, by making named parameters explicit at the declaration site - for
example, use curly braces in the declaration to designate named arguments:

  function makeCar({ int $yearOfProduction, string $vin }) {
// ...
  }

This way, adding named parameters is not a breaking change - it's an opt-in
feature for those cases where it's useful and meaningful, but it's still
applicable to all the patterns and cases that someone might want to use it
for.

Named parameters is just one possible alternative - I'm just naming it for
practical comparison, to demonstrate how some features may have more
general applications than others.

I'd prefer to see new features that work everywhere, all the time, for
everyone - and for existing code. Rather than adding more features and
syntax for very specific (even relatively rare) use-cases.


On Thu, Sep 12, 2019 at 4:00 PM MichaƂ Brzuchalski <
michal.brzuchal...@gmail.com> wrote:

> Hi internals,
>
> I'd like to open discussion about RFC: Object Initializer.
>
> This proposal reduces boilerplate of object instantiation and properties
> initialization in case of classes without required constructor arguments as
> a single expression with initializer block.
>
> https://wiki.php.net/rfc/object-initializer
>
> I appreciate any 

Re: [PHP-DEV] Re: [RFC] Namespace-scoped declares, again

2019-07-27 Thread Rasmus Schultz
On Thu, Jul 25, 2019 at 3:34 PM Nikita Popov  wrote:

...
> Based on the received feedback, I plan to change this proposal from being
> "namespace-scoped" to being "directory-scoped" instead

...


I think that's a better approach.

But please consider doing this without adding another global function that
defines more global (compiler) state?

If it's going to be directory-scoped, using some kind of project root file,
in my opinion, is the more traditional way to declare directory-scoped
boundaries.

For example, if you could just put a "php.json" file in the root of your
namespace folder, this becomes very easy to spot next to your ".gitignore",
"composer.json", "package.json", "tsconfig.json" and any other well-known
project configuration files.

Finding these in the root of any project/library is pretty intuitive -
poking through bootstrapping scripts for a global function call, meh, not
so much.

(This file could be used to declare other repetitive things too - for one,
why is the declare() situation any different from having to repeat a
namespace declaration in every file? This is just another global setting
that could just as well be declared once in a project root file. If this
file were parsable or reflectable by e.g. Composer, this could probably be
used to make the "autoload" section in Composer optional, for one.)

(You could expand upon this feature in the future to add other compiler
options - for instance, toggling global functions, which would allow for
things like correcting inconsistent argument order in the standard
libraries, toggling incompatible language features, toggling improved
defaults for certain functions, a proper strict type-checking mode at some
point in the future, etc...)


Re: [PHP-DEV] Stop replacing dots with underscores in query, post and cookie parameters for PHP 8?

2019-07-18 Thread Rasmus Schultz
On Thu, Jul 18, 2019 at 4:28 PM Dan Ackroyd  wrote:

> On Thu, 18 Jul 2019 at 11:08, Rasmus Schultz  wrote:
> >
> > What about ...
>
> Although there might be real problems for this, please can you
> describe a concrete problem that will occur, in a library people use,
> rather than a vague possible problem?
>

Well, both underscores and hyphens are permitted in header names - so a
library that replaces underscores with hyphens potentially mangles real
header names. (Mangling and unmangling are both lossy operations.)


> For most framework users, all of the request variables are only
> accessed through either a PSR7 request object or their framework
> specific equivalent, and the problem of mangling/demangling can be
> solved there.
>

Yes, that's my concern - if they don't know whether the names are already
mangled or not, they might apply the unmangling, unintentionally mangling
actual valid header names.

Besides also wasting some CPU time - no point in processing header-names if
they're already properly formatted.

Mainly, all I'm suggesting is that there be some way to tell if the names
were either never mangled, or have already been unmangled, so we can avoid
single or multiple (redundant and/or lossy) mangling/unmangling operations
in the polyfill and PSR-7 libraries.

Since this has to do with $_SERVER, it seems natural to keep it in
$_SERVER["REAL_HEADER_NAMES"], which would be set to true on PHP 8.

So in the polyfill:

if (isset($_SERVER["REAL_HEADER_NAMES"])) {
// mangle names...
unset($_SERVER["REAL_HEADER_NAMES"]);
}

And in the PSR-7 libraries:

if (isset($_SERVER["REAL_HEADER_NAMES"])) {
// use names as is
} else {
// unmangle names
}

This is just an example - I'm indifferent as to the name and location of
this value.

Someone suggested using a constant, but you can't unset a constant - for
the polyfill and PHP 8 both to be seen by a PSR-7 library as having real
header names, the polyfill needs to be able to clear that flag. (With a
constant, you'd need an additional check against php_version() - just
trying to keep this as simple as possible.)


Re: [PHP-DEV] Stop replacing dots with underscores in query, post and cookie parameters for PHP 8?

2019-07-18 Thread Rasmus Schultz
On Tue, Jul 16, 2019 at 2:34 PM Bishop Bettini  wrote:

> On Tue, Jul 16, 2019 at 3:51 AM Nikita Popov  wrote:
>
> > On Tue, Jul 16, 2019 at 3:40 AM Arnold Daniels <
> > arnold.adaniels...@gmail.com>
> > wrote:
> >
> > > Hi,
> > >
> > > PHP replaces dots with underscores for $_GET, $_POST and $_COOKIE. This
> > > behavior once made sense because of Register globals. The explanation
> in
> > > the manual also still implies that query and post parameters are
> > converted
> > > to variables (see
> > >
> >
> https://php.net/manual/en/language.variables.external.php#language.variables.external.dot-in-names
> > ).
> > > Register globals has been removed since 5.4.0 and thus this behavior
> > serves
> > > little purpose.
> > >
> > > I think it would be good to remove the conversion in PHP 8, as it's a
> > > general cause of confusion and annoyance for anyone who comes across
> it.
> > >
> > > Is there a good reason to keep this behavior in PHP 8?
> > >
> >
> > This has been discussed a few times already, and I think that everyone
> > agrees that this behavior should go, but not necessarily on the migration
> > path. There is an RFC here:
> > https://wiki.php.net/rfc/on_demand_name_mangling
> > I think that the latest version of that RFC, that basically proposes to
> > drop the behavior and tell people to use a polyfill is fine.
> >
>
> I've readied the proposal for formal discussion. As proposed:
>
>- PHP 8.0 will no longer mangle variable names in any super-global.
>- The changelog will recommend auditing super-global access for mangled
>names, and replacing with the actual variable name.
>- No INI settings will engage the behavior.
>- No warnings or notices will be emitted.
>- A polyfill will be made available to emulate that original behavior.
>- Applications requiring name mangling shall invoke the polyfill during
>bootstrap phase.
>
> https://wiki.php.net/rfc/on_demand_name_mangling


What about libraries that need to support both PHP 7 and 8? Many libraries
will likely need to, potentially for a long time.

How will these libraries be able to detect whether the names have been
mangled or not? Libraries that "unmangle" run the risk of "unmangling"
names that aren't actually mangled, and could end up mangling them instead.

This is a particular concern with the proposed polyfill - if there's a
polyfill that mangles the names, you can't just use something like
php_version() to check if it's version 8, since the polyfill could have
been applied.

Maybe consider adding something like $_SERVER["REAL_HEADER_NAMES"] which,
if set, will indicate the names have not been mangled? The polyfill could
then unset() this value - it could even check first if the names are
already non-mangled, whether this is because it's running under PHP 8,
because the polyfill gets bootstrapped twice (which it'll probably need to
check somehow anyway) or because somebody else polyfilled the same change
in some other way.


Re: [PHP-DEV] Deprecate short_open_tag ini directive?

2019-03-25 Thread Rasmus Schultz
For the record, we're a mid-size organization, building a modern product on
PHP 7 with a PSR-based stack.

We've shunned template engines and rely heavily on short open tags and
alternative control-structures - mainly because we insist on static
analysis and IDE support, which we get by manually type-hinting a single
view-model variable $view at the beginning of each template.

No other template engine gives us what we want in terms of static analysis,
type-checking or IDE support.

The choice to rebuild a very large product in PHP vs e.g. Node, at the
time, was in part motivated by PHP's template features - which, while it
may look pretty verbose and ugly on the surface, has a huge advantage over
basically anything else, e.g. static analysis with various QA tools,
automated refactorings (rename etc.) in PHP Storm, and so on.

The loss of this feature would be a substantial setback for our
organization - for which there is no really good replacement.


On Tue, Mar 12, 2019 at 10:51 AM Rowan Collins 
wrote:

> On Mon, 11 Mar 2019 at 20:06, G. P. B.  wrote:
>
> > From my understanding, the ` directive,
> > so maybe we should deprecate PHP's short tag altogether?
> >
>
>
> I think when that's been proposed in the past, people have said they like
> it for use in simple templates, often along with the "alternative control
> structures", e.g.:
>
> 
> quantity > 1 ): ?>description; ?> endif; ?>
> 
>
> I couldn't find any discussions for a few years, though, so it's possible
> opinions have changed.
>
> Regards,
> --
> Rowan Collins
> [IMSoP]
>


[PHP-DEV] unload/reload classes?

2019-03-18 Thread Rasmus Schultz
Hello internals,

How hard would be to add an unload (or reload) feature for
classes/interfaces?

I'm wondering with regards to running PHP as a deamon (with Swoole or
ReactPHP, etc.) could it be made possible to hot-reload e.g. for
controllers and view-models?

Of course, the other option is to launch worker sub-processes under some
sort of host process, and then restart the workers after a change - this
adds communication overhead between the host/worker processes though, and a
layer of complexity.

Another option is if a reverse proxy (NGINX maybe) could restart the actual
application daemon, but that means you have a dependency on a specific
reverse proxy.

So I know there are other options, but I'm looking for the simplest and
cleanest way to do this, and I'd prefer to stay within the language.

Other dynamic languages (where daemonizing is "normal", like Ruby, JS and
Python) have this feature and it is often used to hot-reload
controllers/views in web-apps.

Any thoughts?


Re: [PHP-DEV] [RFC] JIT

2019-02-18 Thread Rasmus Schultz
> 1.3-1.5 times speed-up

Dare I ask.

But is this even worth while?

This does not bring PHP to the level of performance where you could
reasonably implement, say, interpolated image resampling or a JPEG
decoder/encoder, correct?

This is still orders of magnitude slower than C, am I wrong?

Please don't think that I'm trying to shit on anybody's hard work, and
forgive me for asking, but how much maintenance overhead does the JIT add
to the language going forward?

Will this significantly slow down the development of every new language
feature?

If not, then by all means, please continue :-)

But if this is adding substantial maintenance overhead or significantly
increasing the barrier for contributions, I'd say, think very carefully
about this.

Developers are not picking a dynamic scripting language for the excellent
performance, unless we're talking near-C level performance (e.g. Lua-JIT
and, to my knowledge, not much else) and I don't get the impression this is
anywhere in that neighborhood?

Again, really not trying to bring down this very impressive piece of work -
but, as with any new language feature, we need to weigh complexity against
benefits, and I'm not convinced this kind of speed-up really opens PHP to
any new use-cases?

Being faster is always nice, but unless it's actually "fast", by which I
mean "fast enough to enable doing something new", it's only nice - it's not
necessarily a must.

For example, if this doesn't rival the performance of, say, WASM,
integration of a WASM engine might be a more worth while pursuit in the
long term.

Just wondering.

Please try not to see this post as aggressive or negative - I just hope
we're entering into such a major language change with eyes open? :-)

Thanks.


On Thu, Feb 14, 2019 at 7:45 AM Dmitry Stogov  wrote:

>
>
> On 2/14/19 3:02 AM, Eugene Leonovich wrote:
> > On Tue, Feb 5, 2019 at 6:06 PM Bruce Weirdan  > > wrote:
> >
> > On Tue, Feb 5, 2019 at 8:38 AM Dmitry Stogov  > > wrote:
> >  > > PHP+optimizer (-dopcache.jit_buffer_size=0):  32.29s  (100%)
> >  > > PHP+optimizer+JIT (-dopcache.jit_buffer_size=5000): 30.72s
> > (95.1%)
> >  > > PHP+optimizer+minimalJIT (-dopcache.jit_buffer_size=5000
> >  > > -dopcache.jit=1201): 29.95s (92.7%)
> >  >
> >  > It may be interesting to try -dopcache.jit=1235. It should JIT
> > only hot
> >  > functions and requires some warm-up.
> >
> > For this use case 1201 was the fastest of all the options I tried
> > (including 1235).
> >
> > --
> > PHP Internals - PHP Runtime Development Mailing List
> > To unsubscribe, visit: http://www.php.net/unsub.php
> >
> >
> >
> > Here are my results of benchmarking rybakit/msgpack.php:
> >
> > bench.php, w/o jit:
> >  Total 9.8220 4.3121
> >
> > bench.php, opcache.jit=1235 opcache.jit_buffer_size=256M:
> >  Total 8.7255 3.3350
> >
> > bench2.php, w/o jit:
> >  pure msgpack: 2.2818 sec
> >  pure msgpack packed: 2.1717 sec
> >
> > bench2.php, opcache.jit=1235 opcache.jit_buffer_size=256M:
> >  pure msgpack: 1.5221 sec
> >  pure msgpack packed: 1.4739 sec
> >
> > Details:
> https://gist.github.com/rybakit/bb551f962b706a9e08c995cf5ed9762f
>
> 1.3-1.5 times speed-up.
> Thanks for benchmarking.
>
> Dmitry.
>


Re: [PHP-DEV] proper anonymous classes?

2019-02-13 Thread Rasmus Schultz
It doesn't have to be?

It could just be an inline class expression (without the new keyword) that
evaluates to a string, e.g. a machine-generated class-name?

I don't think that's what first-class support means? e.g. nothing like
constructors in JS or class instances like Dart?

This could just be a "cheap hack" with machine-generated class-names, so we
can reference anonymous classes by name, the same way we reference classes
now.

Introducing classes as instances of some kind of "class class" would be a
more drastic change, since this would not be compatible with existing
string type-hints for class-names. (?)

On Wed, Feb 13, 2019 at 9:16 AM Joe Watkins  wrote:

> What you describe is first class support for classes, nothing much to do
> with anonymous classes.
>
> On Wed, 13 Feb 2019, 09:01 Rasmus Schultz 
>> The fact that the anonymous class syntax defines a class *and* immediately
>> constructs an instance is quite annoying.
>>
>> For one, this is quite incompatible with DI containers' ability to resolve
>> constructor arguments.
>>
>> Lets say you DI container can register a named component by merely
>> referencing a class that uses constructor injection - so lets say this
>> works:
>>
>> class MyController {
>> public function __construct(MyService $service) {
>> // ...
>> }
>> }
>>
>> $container->register("my-controller", MyController::class);
>>
>> Now I want to register an anonymous class, for example as part of an
>> integration test-suite, which is common enough:
>>
>> $container->register("my-controller", new class {
>> public function __construct(MyService $service) {
>> // ...
>> }
>> });
>>
>> This doesn't work, because you're expected to actually pass the
>> constructor
>> arguments immediately - because you can only define an anonymous class
>> while immediately creating an instance.
>>
>> What I really want is just an anonymous class - not an instance, so:
>>
>> $container->register("my-controller", class {
>> public function __construct(MyService $service) {
>> // ...
>> }
>> });
>>
>> The question is, what would a class expression without the new keyword
>> evaluate to?
>>
>> Since we normally reference classes with just a class-name, I guess I'd
>> expect a string, like you'd get from the ::class constant.
>>
>> Any hope for something like that?
>>
>


[PHP-DEV] proper anonymous classes?

2019-02-13 Thread Rasmus Schultz
The fact that the anonymous class syntax defines a class *and* immediately
constructs an instance is quite annoying.

For one, this is quite incompatible with DI containers' ability to resolve
constructor arguments.

Lets say you DI container can register a named component by merely
referencing a class that uses constructor injection - so lets say this
works:

class MyController {
public function __construct(MyService $service) {
// ...
}
}

$container->register("my-controller", MyController::class);

Now I want to register an anonymous class, for example as part of an
integration test-suite, which is common enough:

$container->register("my-controller", new class {
public function __construct(MyService $service) {
// ...
}
});

This doesn't work, because you're expected to actually pass the constructor
arguments immediately - because you can only define an anonymous class
while immediately creating an instance.

What I really want is just an anonymous class - not an instance, so:

$container->register("my-controller", class {
public function __construct(MyService $service) {
// ...
}
});

The question is, what would a class expression without the new keyword
evaluate to?

Since we normally reference classes with just a class-name, I guess I'd
expect a string, like you'd get from the ::class constant.

Any hope for something like that?


[PHP-DEV] Mixed type-hint

2019-02-07 Thread Rasmus Schultz
Regarding the mixed type-hint RFC:

https://wiki.php.net/rfc/mixed-typehint

> When no native type is present, it is unclear what type is expected

Regarding variance - in the examples shown in the RFC, it is still unclear
whether your intention was variance, or if you just omitted the type-hint
by accident.

The introduction of the mixed type-hint, as I was trying to explain
earlier, could have addressed that problem - by allowing mixed variance
only with an explicit type-hint and disallowing implicit variance.

As I pointed out when the variance RFCs were accepted, it's too late to
remove this allowance now, as that would be a breaking change.

However, could we at least make it an E_STRICT?

So that, given the following:

class A {
public function foo(int $value) {}
}

The following would emit an E_STRICT:

class B extends A {
public function foo($value) {} // E_STRICT: implied variance
}

And the following would not:

class B extends A {
public function foo(mixed $value) {} // explicit variance
}

An E_STRICT is not a breaking change, right?

At least then we can map E_STRICT to an ErrorException during development.

Without this, the mixed type-hint is basically meaningless noise, is it
not? About as effective is a doc-block?


[PHP-DEV] Possible bug in the implementation of php://input streams?

2019-01-16 Thread Rasmus Schultz
We've noticed something odd about the "php://input" stream.

This type of stream resource reports itself as seekable:

assert(stream_get_meta_data(fopen("php://input", "r"))["seekable"] ===
true);

https://3v4l.org/EFLiO

If you attempt to rewind() it after reading the stream, rewind() returns
true, and ftell() subequently returns 0.

However, attempting to read the stream again after that returns nothing.

On the other hand, if you fopen() a new resource, it is readable again
after all.

So it seems, either the "php://input" stream implementation is somehow
broken - or it's incorrectly reporting as seekable?

Any idea?


Re: [PHP-DEV] deprecation of set_error_level() callback $errcontext argument

2018-10-03 Thread Rasmus Schultz
On Tue, Oct 2, 2018 at 11:37 PM Rowan Collins  wrote:

> While I can understand the desire to have debugging feature built into
> the language "out of the box", it may be best left to extensions which
> can capture the information to a log or wherever without providing the
> full flexibility of the language to interact with it.

I think, since the language *did* provide this "out of the box", it's sort of
odd to deprecate a feature that is being used by a popular product - the
Sentry PHP package has 8 million downloads, and PHP developers rely
on this in production to help them fix bugs. Seems pretty important?

And an extension isn't really an acceptable alternative to someone who
was offering a product that "just worked".

For example, rather than removing this feature, might it be possible to
deeply clone the variables and provide backwards compatibility in that
manner? I doubt that anyone is counting on introducing side-effects via
an error-handler, but surely it's not uncommon for error-aggregators and
loggers to rely on this information being available?

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



[PHP-DEV] deprecation of set_error_level() callback $errcontext argument

2018-10-02 Thread Rasmus Schultz
I understand the $errcontext argument to the set_error_level()
callback was deprecated in 7.2.

Apparently, this was deemed "not useful", but what's the alternative?

I understand that debug_backtrace() reports the arguments on the
call-stack, but... just the arguments - no local vars.

I understand you want people to use a real debugger, but there's also
such a thing as error-handling in production - this information was
logged and was useful in conjunction with Sentry, and probably other
error-handlers.

But this feature has been removed, and there's no alternative?

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



Re: [PHP-DEV] Re: Pre proposal for "Class extension functions"

2018-09-26 Thread Rasmus Schultz
On Mon, Sep 24, 2018 at 11:24 PM Andrew Gromov  wrote:

> > Bring a little Javascript into PHP?
>
> In fact, I looked at Kotlin :)

Kotlin does not modify classes.

This sort of thing is sound in compiled languages like Kotlin and C#, where
this is really syntactic sugar for calling user-defined functions with
object-like
syntax - it's possible (and sound) *only* because these languages can resolve
such calls at compile-time.

In dynamic languages like JavaScript, you're literally writing to a
map of methods,
which means execution order is critical, and overwrites are possible - just two
reasons why this feature isn't sound in languages like JavaScript, and wouldn't
be in PHP either.

What's wrong with just calling a function and passing the object as argument?

In my opinion, this is the kind of pointless feature that brings nothing new and
invites inconsistent code and bikeshedding over pointless details.

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



Re: [PHP-DEV] [RFC] [VOTE] Typed properties v2

2018-09-23 Thread Rasmus Schultz
> That is the entire point of the elephant analogy: that knowing what can
get in doesn't necessarily mean knowing what is already inside - BUT,
knowing what can get in may still useful in itself.

I understood that, and I disagree - just knowing what can get in is not
useful or interesting in itself. It's not even a new language feature - you
can already achieve the same with a simple setter. It's just new syntax.

The only reason it's interesting to control what can get inside with type
hints, is to enable the language to do something new - something it
couldn't already do, which is to guarantee that the type enforces it's own
state specification.

I understood the analogy, and I don't agree.


On Sun, Sep 23, 2018, 00:42 Rowan Collins  wrote:

> On 22 September 2018 20:32:04 BST, Rasmus Schultz 
> wrote:
> >if you read my last post (especially the last part) carefully, you'll
> >see
> >why this elephant analogy is incomplete.
> >
> >the issue is not whether or not something gets in - it's much more far
> >reaching than that.
> >
> >the issue is, once something gets in, can you even be sure that that
> >something is what it claims to be?
>
> That is the entire point of the elephant analogy: that knowing what can
> get in doesn't necessarily mean knowing what is already inside - BUT,
> knowing what can get in may still useful in itself.
>
> The positions being expressed are therefore, roughly:
>
> a) That it's not the job of this feature to prove what is inside, only to
> guard the door. (That is, that the current implementation is sufficient.)
>
> b) That it is vital to always know what is inside, regardless of how it
> got there. (That is, that we must prevent all mechanisms where the value is
> uninitialised.)
>
> c) That there will always be some ways for the wrong thing to end up
> inside, but that we can add checks at key moments to see if that's
> happened. (That is, that we should detect uninitialised values
> automatically at the end of the constructor, and in similar places, but
> that there well be other ways that uninitialised values can come about.)
>
> In your last message, you seemed to be accepting position c - that not all
> scenarios could be prevented, but that the common case of the constructor
> should be checked. That is the same position Larry is suggesting, so I'm
> not sure why you seem keen to disagree with him.
>
> Regards,
>
> --
> Rowan Collins
> [IMSoP]
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] [RFC] [VOTE] Typed properties v2

2018-09-22 Thread Rasmus Schultz
Larry,

this wasn't aimed at "you" personally, I'm just using the proverbial "you",
as in "not me".

if you read my last post (especially the last part) carefully, you'll see
why this elephant analogy is incomplete.

the issue is not whether or not something gets in - it's much more far
reaching than that.

the issue is, once something gets in, can you even be sure that that
something is what it claims to be?

at the moment you can't, and that's a serious issue - type hints appear to
provide some guarantees that in fact aren't provided at all. it's
confusing, and the explanations are more complex than they need to be.

(and I guess that's generally an issue in very dynamic languages, but type
hints are supposed to provide a means to improve on these problems where it
makes sense - not make the problems worse.)

On Sat, Sep 22, 2018, 20:32 Larry Garfield  wrote:

> Rasmus: Please be careful when you refer to "you" as wanting or doing
> something.  I had no part in the patch design or implementation beyond
> saying
> "yay!" a few times on the list/twitter.  "I" don't want a particular
> engine
> pseudo-type (uninitialized); I honestly don't care about that level of
> implementation detail.  I am only trying to offer suggestions for how to
> tighten the guarantees further without violating the basic facts of how
> PHP
> works.
>
> On Saturday, September 22, 2018 12:12:48 PM CDT Rowan Collins wrote:
> > On 22/09/2018 11:15, Rasmus Schultz wrote:
> > >> That is, it doesn't assert that a value IS a given type, but that it
> can
> > >> only be SET TO a given type.
> > >
> > > That is literally the same thing - if it can only be set to a given
> > > type, it can only BE a given type.
> >
> > Consider this analogy: if I build a house with a standard, human-sized
> > door, I cannot walk an elephant through that door; however, if the
> > elephant was already there, I could build the house around it. So, the
> > assertion that "no elephant can get in through that door" is not the
> > same as the assertion "there is no elephant inside that house". If
> > you're interested in protecting your house from roaming elephants, the
> > small door is probably sufficient for your needs; if you want to know
> > that when you walk into a house, there is no elephant inside, you need
> > other assurances.
> >
> > What Larry is pointing out is that Levi and Marco are happy to make the
> > door elephant-proof (prevent nulls being assigned to the properties);
> > whereas you and I are looking for a stronger guarantee that there will
> > never be an elephant inside (that the object will not be in an invalid
> > state).
>
> LOL.  Rowan, I love that analogy.  It expresses the problem space very
> well.
>
> > > I don't think that, and I don't expect that - I'm not suggesting we
> > > enforce
> > > anything statically, I'm merely suggesting that a constructor needs to
> > > satisfy the constraints specified by the class.
> >
> > If you read carefully, that's exactly what Larry's proposal below
> requires.
> >
> > >> To wit, could we add an engine check to scan an object and make sure
> its
> > >> objects are all type valid right-now (viz, nothing is unitialized),
> and
> > >> then call it on selected actions automatically and allow users to call
> > >> it at arbitrary times if they are doing more esoteric things?
> > >
> > > In my opinion, this is a solution to the problem we created when we
> > > decided
> > > every property should internally be annotated with an "initialized"
> > > boolean
> > > property - you have all this extra state that wasn't part of the
> > > specification of the class itself, and now you have to deal with that
> > > state.
> > >
> > > In my opinion, tracking this extra state *during the constructor call*
> is
> > > acceptable and necessary in a scripting language like PHP - I never
> > > asked for static type-checking, I'm merely asking for this check to be
> > > built-into the language and performed at run-time when you exit the
> > > constructor, e.g. at the last moment where you can feasibly perform
> > > this check.
> >
> > I'm not sure if you've misunderstood Larry's proposal, or are just
> > agreeing with it: the sentence you quote says "add an engine check" and
> > "call it on selected actions automatically"; and you ask for it to be
> > "built-into the language and performed at run-time"; you mention it
> &g

Re: [PHP-DEV] [RFC] [VOTE] Typed properties v2

2018-09-22 Thread Rasmus Schultz
I apologize for the long posts, but Larry asked me to comment on this.

On Thu, Sep 20, 2018 at 5:52 PM Larry Garfield  wrote:

> I think the distinction here is that one group is arguing for "state of the
> data assertions" while the RFC as implemented is "setter assertion shorthand".

The point of the setter assertions is to provide guarantees about the state of
the data - there is literally no difference.

> That is, it doesn't assert that a value IS a given type, but that it can only
> be SET TO a given type.

That is literally the same thing - if it can only be set to a given
type, is can only
BE a given type.

The problem here is you want to make exemptions for null as type - as though
nulls aren't types (which they are) and as though nullable types aren't distinct
from the types they're derived from. (again, they are.)

> I don't think a complete IS enforcement is possible given PHP's nature.

I don't think that, and I don't expect that - I'm not suggesting we enforce
anything statically, I'm merely suggesting that a constructor needs to satisfy
the constraints specified by the class.

If you've type-hinted a property as int, you don't allow strings - that would be
pointless, right?

But that is precisely the problem we're talking about - if you've type-hinted a
property as non-nullable int, it shouldn't allow null... but that is
literally the
exemption you want to allow for - you just want to annotate the property
with an additional meta-data property "unintialized", which is literally the
same as adding a boolean "is set" for every property in your model.

> This isn't a compile time check
> either:
>
> $b = 'foo';
> test($b);
>
> It's a runtime TypeError, not compile time.

This actually illustrates my point nicely - the variable $b in this
case has nothing
to do with the state of the parameter var inside the function body,
until you pass
it via a function call. That's perfectly fine. You'll get an error at
the point where
the parameter type-constraint was violated - you can look at a stack-trace and
debug that easily.

Now take your example and call a constructor instead of a function:

class Test {
public string $b;
}

$b = 'foo';
$test = new Test();

Your constructor call generates no run-time error here, and the program
continues to execute with $test in a state that, according to specification of
the class itself, isn't valid.

Since the constructor is how a valid instance of Test gets generated in the
first place, you've missed your *only* chance to enforce those constraints -
meaning, you've missed the only opportunity you had to verify that the
constructor does in deed generate an instance of Test that lives up to
Test's own specification of what a Test instance is.

> To wit, could we add an engine check to scan an object and make sure its
> objects are all type valid right-now (viz, nothing is unitialized), and then
> call it on selected actions automatically and allow users to call it at
> arbitrary times if they are doing more esoteric things?

In my opinion, this is a solution to the problem we created when we decided
every property should internally be annotated with an "initialized" boolean
property - you have all this extra state that wasn't part of the specification
of the class itself, and now you have to deal with that state.

In my opinion, tracking this extra state *during the constructor call* is
acceptable and necessary in a scripting language like PHP - I never
asked for static type-checking, I'm merely asking for this check to be
built-into the language and performed at run-time when you exit the
constructor, e.g. at the last moment where you can feasibly perform
this check.

If you don't perform that check, you have no guarantees at all.

Consider this example:

function login(int $user_id) {
  // ...
}

Inside the body of this function, you can safely assume you have an integer,
right? A basic guarantee provided by the language.

Now consider this alternative:

function login(User $user) {
  // ...
}

Inside the body of this function, you'd assume you have a valid instance
of User, right? The same basic guarantee provided by the language.

Wrong. Something might be "unintialized". This might in fact not be a valid
instance of User, it might be only partially initialized.

This is a problem, because I want my type User to be a reliable type - as
reliable as any other type.

Integers for example is nice, because I know I'm going to be able to add,
subtract, multiple, divide, and so on - if you've type-hinted a parameter as
int, you know it has those abilities, you know the + operator isn't going to
fail because there's a special kind of int that doesn't work with the
+ operator.

We want those same guarantees from our own types, that's all.

In the case where a type *doesn't* provide such a guarantee, it can explicitly
state that something is nullable - not guaranteed to be set. You have that
option already, you don't need unintialized properties for that.

If there 

Re: [PHP-DEV] [RFC] [VOTE] Typed properties v2

2018-09-21 Thread Rasmus Schultz
On Fri, Sep 21, 2018 at 10:24 AM Lester Caine  wrote:

> Ignoring the debate on uninitialized/null ... not all objects ARE
> invariant

hence nullable types.

> and there are very good reasons for not setting values for
> everything, but it seems that these types of object are deemed to be
> 'bad coding' where in fact the simply have elements that yet to be
> 'initialized' if at all for this instance of the object.

that's what nullable types are for.

> The constructor
> simply creates those elements that need to exit and does nothing with
> the holders for elements that have yet to be populated ... they stay null.

hence nullable types.

the point of using type-hints on the properties of a class is to describe
the invariant state of that class - if the state of an instance of that class
is not what the class itself prescribed/promised at the time when you
return from the constructor, what's the point?

the only difference between using nullable vs non-nullable property
type-hints then, is whether you can set them *back* to null after setting
them to value - but it's okay for them to return from the constructor in
a "null-like" state?

this doesn't provide *any* additional guarantees:

class Foo {
public int $bar;
}

$foo = new Foo(); // invalid state allowed

$foo->bar = 123; // valid state

$foo->bar = null; // invalid state NOT allowed?!

Have the effects on the null coalesce operator even been considered?

$bar = $foo->bar ?? "what";

Is unintialized "null-like enough" or will this trigger an error?

Extremely confusing.

Type-annotations are essentially assertions about the state of a program -
if you can't count on those assertions to be fulfilled (which you
can't if they're
not checked at the time of initialization) then they're not useful.

The bottom line for me is that property type-hints were supposed to make
my programs more predictable, make the language more reliable.

Instead, we've introduced a whole new kind of uncertainties, new ways to
write unpredictable code, a new kind of null that makes the language even
more unreliable.

In terms of reliability, it's actually sub-par to hand-written accessors.

Shorter syntax, reflection support, great - but ultimately at the cost of
reliability and predictable state.

For one, what good is reflection, if it tells me I can expect a property to be
an integer, and it turns out it doesn't have a value after all?

If you want horrible code with no guarantees, there are plenty of ways to
do that already - you don't need property type-hints for anything more than
mere convenience in the first place.

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



Re: [PHP-DEV] [RFC] [VOTE] Typed properties v2

2018-09-21 Thread Rasmus Schultz
On Thu, Sep 20, 2018 at 4:50 PM Levi Morrison  wrote:
>
> This will be my last reply to this thread. Fundamentally:
>
> class User {
>  public ?int $id;
>  public ?string $preferred_name;
>  public ?string $username;
>  }
>
> ^ This permits null properties at all times. This is acceptable
> behavior if null is valid for the domain. It is not valid for this
> domain -- all 3 are required.

If all three are required, your constructor needs to reflect that.

The reason constructors even exist in the first place is to initialize
the object's data members and establishing the invariant of the class.

Constructors are supposed to prepare objects for use.

Your (empty, implicit) constructor isn't doing that.

Your reasoning about this is circular - you want your properties to
be optionally initialized and non-null at the same time. You get
around this by coming up with a new term "undefined" for a
special kind of null that triggers run-time exceptions on read.

The whole idea is unnecessarily complex, and will certainly lead
to silent bugs that allow partially-initialized domain objects to
pass through many layers of a system without getting caught
until some code tries to read an "uninitialized" property.

function make_foo(): Foo {
   return new Foo(); // missing a property
}

function x() { ... }
function y() { ... }
function z() { ... }

x(y(z(make_foo()));

The instance travels through layers and layers of callls and
fails somewhere in the x() or y() function because of a missing
value ... why was the value missing? why wasn't it initialized?
where was it supposed to have been initialized? where did
this bad instance of Foo even come from?

All that information is lost in a call-stack that's long gone by
the time you invoke x() and you'll have to backtrack through
layers and layers of code to try to figure out where this bad
instance came from.

This will be an everyday thing with code like that.

To say that we don't need to enforce invariants at the time of
construction is to say we don't need to enforce them at all -
enforcing them "maybe later" is the same as not enforcing
them. That is, when they trigger an error, it's no different
from a null-value triggering a similar error.

No matter how you twist it, uninitialized is the new null.

I'm fine with unintialized as an implementation detail that
ensures you can't read from properties while the constructor
is busy establishing the invariant.

I'm not at all fine with unintialized as a new language feature.

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



Re: [PHP-DEV] [RFC] [VOTE] Typed properties v2

2018-09-20 Thread Rasmus Schultz
On Wed, Sep 19, 2018 at 10:04 PM Levi Morrison  wrote:

> I think this code should be allowed:
>
>class User {
> public int $id;
> public string $preferred_name;
> public string $username;
> }

This code is broken - by making the properties non-nullable, you're
literally saying "these properties will be initialized", then
proceeding to not initialize them. That's just incomplete code.

Note that we're talking about two different things here - I was
talking about bypassing declared constructors for technical reasons.

You're talking about omitting constructors from the declaration - but
all classes have a constructor. Not declaring it just implies an empty
constructor. You can even invoke it using reflection.

For your use-case, assuming you insist on writing bad code, is more
accurate like this:

class User {
 public ?int $id;
 public ?string $preferred_name;
 public ?string $username;
 }

These properties are valid without a constructor. You can safely infer
them as null, rather than as "uninitialized".

Non-nullable properties aren't valid without initialization. Not in
any language I've ever heard of.

Maybe PHP has to be the first to prove every other language right?

We have enough half-baked features and inconsistencies as it is.

We'll regret this forever. Like how Javascript developers regret
having null and undefined on a daily basis.

Uninitialized is the new null - it's the PHP equivalent of undefined
in Javascript.

Please no.

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



Re: [PHP-DEV] [RFC] [VOTE] Typed properties v2

2018-09-19 Thread Rasmus Schultz
On Wed, Sep 19, 2018 at 7:43 PM Rowan Collins  wrote:

> I agree that this is a hard problem, but I don't agree that this decision
> is being made "for now". If we allow "non-nullable but uninitialized"
> properties now, it will be extremely hard to change their behaviour in
> future.

I'm with Rowan on this one.

This concept of "uninitialized" frankly seems like an allowance for
people who insist on writing poor code.

Nulls are bad, and "unintialized" is just another kind of "null" with
a built-in run-time type-check that executes on read - too late.

The first example given is just bad:

class Point {
public float $x, $y;

private function __construct() {}

public static function fromEuclidean(float $x, float $y) {
$point = new Point;
$point->x = $x;
$point->y = $y;
return $point;
}
}

You define two invariants: $x and $y must be floats - and then proceed
to break those constraints in the constructor?

Wrong. The RFC itself accurately states that "this code can be
rewritten to indirect through __construct() instead" - as shown in the
previous example.

Now why would you deliberately open the fences and knowingly invite
people to write poor code like this?

As for the second example:

class Point {
public float $x, $y;

public function __construct(float $x, float $y) {
$this->doSomething();
$this->x = $x;
$this->y = $y;
}
}

If doSomething() attempts to read an uninitialized property while the
constructor is still executing, throwing a helpful "uninitialized"
error is fine.

But, in my opinion, once the constructor has executed, the invariants
as declared by the class itself must be satisfied.

If there's one meaningful use-case for allowing objects in a
partially-initialized state, it's during
hydration/unserialization/reflection scenarios, maybe - but in those
cases, you're willfully bypassing the constructor; it's not the
everyday 95% use-case and some risk is acceptable here, you'll get
around it with tests. But nobody wants to write tests all day to see
if any classes contain "unininitialized" properties - that misses half
the whole point of being able to declare those types in the first
place, e.g. makes type-hinted private/protected properties totally
unreliable.

Once this is in a release, it'll be unfixable, and in my opinion will
likely go down in history as another one of those little things we
wish we could go back in time and fix :-/

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



Re: [PHP-DEV] [RFC] Mixed type

2018-07-01 Thread Rasmus Schultz
Nikita,

I think we'll need the mixed type-hint in any case if we're to move
ahead with generics?



On Sat, Jun 30, 2018 at 10:30 PM, Nikita Popov  wrote:
> On Sat, Jun 30, 2018 at 10:17 PM, Sara Golemon  wrote:
>
>> On Sat, Jun 30, 2018 at 3:08 PM, Stanislav Malyshev 
>> wrote:
>> >> Together with Michael Moravec, we’d like to announce that we are
>> pretending
>> >> to open the Mixed Type RFC (https://wiki.php.net/rfc/mixed-typehint)
>> next
>> >> Monday (02/07) and we’d like to ask you to take a look into the PR on
>> >> GitHub (https://github.com/php/php-src/pull/2603) and let us know if
>> >> there's something else to do before it.
>> >
>> > I think this is wrong. This "type" - which is not really a type, of
>> > course - does not add anything to the code, by definition - if you take
>> > it out, everything would be the same. Things like that belong in the
>> > documentation. Moreover, it makes the code harder to read, as the reader
>> > should make mental effort to discard this non-type every time it is
>> > mentioned, as it does not carry any information.
>> >
>> I would say that, in a world without union or intersection types, it
>> adds to the readability of the code by explicitly saying, "We accept
>> more than one type here, and we know we accept more than one type
>> here." This is distinct from, "We have no idea what type we accept
>> here."  That adds to readability, it doesn't detract.
>>
>> I preface that with a mention of union/intersection types because that
>> seems to be the *actual* problem this RFC is attempting to cope with
>> while lacking the tools to do it right.  I'm not super excited about
>> this RFC because, as you say, this information could be easily encoded
>> into the docblock for the function/method.  Zero impact to the syntax,
>> same benefit for the programmer and their readability. (More benefit,
>> really, as docblock standards *do* permit union/intersection types.
>>
>
> I'm basically with Sara here. Generally the feature has some merit, but I'm
> sure that given our current type-system, and in particular the lack of
> union types, this feature will be misused to annotate parameters that do
> *not* accept completely arbitrary values, but where "mixed" is the best
> approximation we have. For that reason I would prefer to defer this
> addition until proper union types are supported. In that case mixed would
> be a shortcut for the otherwise somewhat unwieldy type of
> ?(bool|int|float|string|array|object|resource) (modulo the non-existence of
> resource...)
>
> Nikita

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



Re: [PHP-DEV] Better types without runtime checking

2018-06-11 Thread Rasmus Schultz
On Tue, Jun 5, 2018 at 9:22 AM, Rudolph Gottesheim  wrote:
> ...
> Has there ever been a discussion about adding some of those features
> syntactically, but ignoring them during runtime?

That's what Hack does, and one of the main reasons we dropped Hack in
favor of PHP.

PHP is a reflective language - if we add e.g. generics or property
type-hints, omitting run-time reflection and/or run-time type-checks
would be inconsistent with PHP as a language in general.

Inconsistencies in a language are surprising and generally "bad" - if
type-hints lead to run-time type-checks, it's natural to expect that
to work predictably no matter where you type-hint. You shouldn't have
to learn where or when type-hints actually work at run-time and where
they don't.

Similarly, if type-hints are reflected, it's natural to expect all
type-hints to exist in the reflection model somewhere, anywhere that
type-hinting is possible. You shouldn't have to search the manual to
learn that type-hints aren't reflected for properties for some reason,
perhaps because it just hasn't been implemented yet.

Much of the "good" that we expect to be able to accomplish with
generics, for example, won't be possible (or won't make sense) without
being consistently reflected and  run-time type-checked.

For example, in a DI container, I'd expect to be able to do something like this:

class Container {
public function get(?string $name): T {
// ...
}

// ...
}

When calling get(), I'd expect a type-check for the the generic
return-type T, to protect me against internal errors in the Container
implementation - if it returns the wrong type, I want it to fail
immediately at that point, rather than potentially exiting the
call-stack that made this error traceable, making this extremely
difficult to debug.

Similarly, if we had property type-hints:

class Foo {
   int $bar;
}

$foo = new Foo();

$foo->bar = "oops";

Here, I'd expect a type-check when assigning to $bar - omitting that
would be extremely bad, as, very likely, by the time something else
fails because this object is in an invalid state, we've exited the
call stack where the bad value was assigned, making this potentially
very difficult to debug.

I'd also expect to be able to reflect on the property-types in a DI
container, or perhaps in a class that maps form post-data to
properties and performs conversions, etc.

I'm the author of the generics RFC and one of the property-type RFCs,
and both of those RFCs call for both reflection and run-time
type-checking, for the sake of keeping the language consistent.

Hack made some very regrettable decisions in this area, and ultimately
those features were useful at design-time only, for IDE-support - but
we have php-doc for that purpose, and in my opinion, adding those
features before (or unless) we're willing/able to also make them work
consistently with the language, does more harm than good. Making these
features appear to be language features, when in fact that they're
only implemented in the parser and ignored by the interpreter, would
make for an extremely confusing experience.

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



Re: [PHP-DEV] Parse error: Invalid body indentation level

2018-05-28 Thread Rasmus Schultz
> > Yes, this is an expected result under the flexible heredoc RFC. To avoid
> > issues, please use a heredoc label that does not occur within the string.
>
> Hmkay, so code that worked fine with PHP 7.1 and PHP 7.2 breaks with PHP
> 7.3. This breaking change should at least be prominently documented. As of
> right now, I do not see such documentation in UPGRADING.

Wow, I can't believe I didn't think of this when I reviewed that RFC.

This is potentially a pretty serious BC break, really - at least in two cases:

1. Markdown, where indentation can be irregular as well as meaningful.

2. Failing tests!

The latter could prove rather difficult - getting your tests to pass
under 7.2 and 7.3+ might be far from simple, and at the very least
would require test-helpers that conditionally treat whitespace
differently for 7.3+ and earlier versions.

Even inline HTML could potentially suffer, if you have  blocks.

And on top of these unexpected results and test-failures, of course
there may be parse errors for inline content with meaningful
whitespace that was (or wasn't) indented correctly.

Honestly, are there any cases where existing code *benefits* from
changing the existing syntax/feature?

Some people indent inline blocks so that the output ends up with the
desired indentation, rather than the source-code looking pretty - in
those cases, whitespace will now be silently removed and the output no
longer as desired?

Are we positive it wouldn't be safer to just introduce a slight syntax
variation for blocks that treat indentation differently?

(am I blowing this out of proportion?)

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



Re: [PHP-DEV] Re: [RFC] Fiber support (again)

2018-05-07 Thread Rasmus Schultz
I've used Swoole, and it is in deed a very high quality extension - both in
terms of performance and stability.

I haven't used the low-level co-routines, but the HTTP server was rock
steady, no memory leaks, easy to implement and CRAZY fast :-)

Kind of turns PHP into a better version of Node tbh ;-)


On Mon, May 7, 2018 at 5:00 PM, Jefferson Gonzalez  wrote:

> I'm just sneaking into the subject to point out that theres already some
> work on this with the PHP swoole extension, in case it hasn't been
> looked/taked into consideration yet:
>
> https://github.com/swoole/swoole-src#coroutine
> https://github.com/swoole/swoole-src#short-api-name
>
> It has great performance and the event based http server demonstrates how
> well it performs. Great to see stuff like this could be shipped as part of
> the core which transcend PHP uses.
>
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] [RFC] Fiber support (again)

2018-04-30 Thread Rasmus Schultz
  - Using Fiber::resume() to initialize the fiber and resume feels
>>> awkward. Separate methods again would be better here, perhaps
>>> Fiber::init(...$args) and Fiber::resume($send).
>>>
>>> All Fiber created with a suspended status. So make resume to do both the
>>> init and resume
>>> do make sense.
>>>
>>
>> It does't make sense to me. Reading the example in the README and
>> understanding why the first resume() takes two arguments instead of one
>> took me quite some minutes.
>
> This Ruby's Fiber and Lua's coroutine using one resume API to init and
resume
> the coroutine. I do not think a dedicate is really required.

I agree, two methods are probably not required.

But I also agree with Aaron that the verb "resume" is confusing/misleading
here - it implies something has already been running, which isn't the case
when you initially create the Fiber.

I'd suggest changing the name to start() - you can "start" something
whether it's starting for the first time or starting again after a pause,
but to "resume" something, it must have been already running, so it's a bit
confusing.


On Fri, Feb 9, 2018 at 1:12 AM, Haitao Lv  wrote:

>
>
> > On Feb 9, 2018, at 06:22, Niklas Keller  wrote:
> >
> >>
> >>> - How do you determine when a fiber has returned? Looking at the
> source,
> >> it appears Fiber::status() must be used, comparing against constants.
> >> Separate methods similar to Generator would be better IMO. e.g.:
> >> Fiber::alive(), Fiber::suspended(), Fiber::running()
> >>
> >> Offering methods like Fiber::alive, Fiber::running makes no difference
> to
> >> check the Fiber::status() return value. This is just a style issue. And
> as
> >> a language feature,
> >> Fiber only offer the essential API and let other works to the user land.
> >
> >
> > The language should offer a sane API, not the absolute minimum required
> to
> > work for these things.
>
> The Ruby's Fiber do offer a live? method but does not have a getStatus
> method.
> The Lua's coroutine only offer a status method.
>
> So do we really need to offer three additional helper method? Or what is
> your
> advice about these API?
>
> >
> >>> - What about throwing exceptions into a fiber?
> >>
> >> Currently does not support throw exception into the fiber. User land
> code
> >> could check
> >> the value of Fiber::yield and throw exception themselves. The Ruby's
> Fiber
> >> and Lua's
> >> coroutine also does not support such api as well.
> >
> >
> > And throw the exception where? That means async code with fibers can't
> > really handle errors?
>
> Actually you can transfer any thing to Fiber by the resume method. And you
> can
> check the return value of Fiber::yield to handle error.
>
> Fiber is designed as a primitive, low level, and lightweight feature. User
> land
> code seldom not need to use them directly in your normal code.
> So the following is not a big problem,
>
> $a = Fiber::yield(...);
> if ($a === false) {
>throw new Exception(...);
> }
>
> And both the Ruby and Lua does not offer such API as well.
> >
> >>
> >>>
> >>> - Using Fiber::resume() to initialize the fiber and resume feels
> >> awkward. Separate methods again would be better here, perhaps
> >> Fiber::init(...$args) and Fiber::resume($send).
> >>
> >> All Fiber created with a suspended status. So make resume to do both the
> >> init and resume
> >> do make sense.
> >>
> >
> > It does't make sense to me. Reading the example in the README and
> > understanding why the first resume() takes two arguments instead of one
> > took me quite some minutes.
>
> This Ruby's Fiber and Lua's coroutine using one resume API to init and
> resume
> the coroutine. I do not think a dedicate is really required.
>
> The generator cannot be init by it's send method. And if you want to
> implement
> coroutine feature(without stack) by it, you have to write code
>
> function run() {
> if ($this->beforeFirstYield) {
> $this->beforeFirstYield = false;
> return $this->coroutine->current();
> } else {
> $retval = $this->coroutine->send($this->sendValue);
> $this->sendValue = null;
> return $retval;
> }
> }
>
> It is verbose.
>
> See https://nikic.github.io/2012/12/22/Cooperative-
> multitasking-using-coroutines-in-PHP.html
>
> >
> >> Please see Ruby Fiber API https://ruby-doc.org/core-2.2.0/Fiber.html.
> >>
> >>>
> >>> - What happens if the sub1() function in the RFC is invoked outside of
> a
> >> fiber?
> >>
> >> You will get a Fatal Error like
> >> Fatal error: Uncaught Error: Cannot call Fiber::yield out of Fiber
> >>
> >>> - I think a keyword here would be beneficial, even if it has a minor BC
> >> impact. Fibers could then be written like generators. `await` or `emit`
> as
> >> a keyword perhaps? This would be a less verbose API, feel less magical
> (a
> >> static method call that actually pauses execution feels out of place),
> and
> >> would allow Fibers to be returned from methods, named 

Re: [PHP-DEV] GD vs Imagick

2017-09-08 Thread Rasmus Schultz
Yeah, I keep thinking about this.

I'm not sure there's a really good reason why PHP shouldn't come with
best-in-class image support, if it's available - which it sounds like it
is; libvips looks more modern, lower memory and CPU overhead, better
overall really, and appears to be stable and up-to-date?

Yeah, it has dependencies. Doesn't everything? Does it matter, as long as
they're bundled?


On Thu, Aug 31, 2017 at 3:30 AM, Kris Craig  wrote:

> 2. Releasing Imagick with PHP means that the release cycles would need
>
> to be sync'ed. This has proven to be inconvenient in the past when an
> extension has wanted to change the api, but was forced to wait due to
> needed to wait for the next minor/major version of PHP.
>
>
> Why would they need to be synced?  When PHP releases a new version, can't
> we just bundle the latest Imagick build and plug into that?
>
> Sure, having them in sync would yield certain benefits, but none of them
> appear to be deal-breakers to me.  Or am I just missing something?
>
> --Kris
>
>


Re: [PHP-DEV] GD vs Imagick

2017-08-23 Thread Rasmus Schultz
Thank you all for considering the subject and contributing your thoughts.

I understand why Imagick is not attractive as a standard module (even
according to the maintainer) since we can't feasible bundle all it's
dependencies, so I suppose that's a no-go.

The libvips module does in deed look interesting. I suppose this would have
all the same problems though? Lots of dependencies.

So GD wins perhaps mostly because it's small and has fewer dependencies.

Color profiles in my experience are pretty common though - and currently
(silently) leads to mangled images with GD.

I've seen a work-around, as somebody mentioned, which involves parsing the
binary contents of JPEG files, extracting the color profile and injecting
it into a JPEG file after GD has saved it - this is (A) horrible in terms
of memory and CPU usage, and (B) not what most users are going to want in
the first place; you most likely want color profiles moved, which is better
in terms of browser compatibility and performance when delivering images
over the web. So this is not a good work-around.

I wanted to contribute to Intervention Image - a library that abstracts GD
and Imagick behind a common API, but it turns out, this can't be
implemented with GD in PHP, except of course resorting to approaches like
pixel-by-pixel manipulation, for which PHP is totally unsuitable.

Ideally, I think that GD should be fixed, since it's the default (by which
I mean, it's the only option on a standard PHP install) so that libraries
like Intervention Image can deliver predictable results.

I'm not a C developer though, so I can't help with that.


On Thu, Aug 17, 2017 at 7:03 AM, Pierre Joye <pierre@gmail.com> wrote:

> hi Rasmus,
>
> On Tue, Aug 15, 2017 at 5:52 PM, Rasmus Schultz <ras...@mindplay.dk>
> wrote:
> > The following GD issue is all-too common:
> >
> > https://stackoverflow.com/questions/5773032/how-to-stop-
> gd2-from-washing-away-the-colors-upon-resizing-images
> >
> > Basically anyone who's ever accepted uploaded images and resized or
> > converted them, has bumped into this.
> >
> > Only Imagick makes it possible to work around this issue, it's not
> possible
> > with GD, at all - and the internal behavior of GD is arguably "wrong", as
> > the visible output of simply opening and saving a JPEG image with GD is
> > mangled with washed-out colors.
> >
> > I am starting to wonder why GD is the default in PHP?
> >
> > It's a pretty outdated library with a clunky API - we have Imagick with a
> > much more concise API and a ton more useful features.
>
> I disagree here, as old functions are old fashioned, new ones are easy
> to understand and to use. Not OO, but that's a little details (contrib
> welcome). And I disagree with outdated as well. It is focused on
> easiness and most common usages. More features make it depending on
> the requests or available time to actually add them. Performance wise
> it is also similar to similar actions.
>
> > Why is the less-capable image library the default on the PHP platform?
> Why
> > not Imagick?
>
> Imagick is good, but it is a huge library, by its size, features, code
> base (external) and complexity. I would never ever recommend to have
> it bundled or even less by default.
>
> In any cases, both libraries (or the bindings) welcome contributors,
> you are more than welcome too :)
>
> Cheers,
> --
> Pierre
>
> @pierrejoye | http://www.libgd.org
>


[PHP-DEV] GD vs Imagick

2017-08-15 Thread Rasmus Schultz
The following GD issue is all-too common:

https://stackoverflow.com/questions/5773032/how-to-stop-gd2-from-washing-away-the-colors-upon-resizing-images

Basically anyone who's ever accepted uploaded images and resized or
converted them, has bumped into this.

Only Imagick makes it possible to work around this issue, it's not possible
with GD, at all - and the internal behavior of GD is arguably "wrong", as
the visible output of simply opening and saving a JPEG image with GD is
mangled with washed-out colors.

I am starting to wonder why GD is the default in PHP?

It's a pretty outdated library with a clunky API - we have Imagick with a
much more concise API and a ton more useful features.

Why is the less-capable image library the default on the PHP platform? Why
not Imagick?


[PHP-DEV] Binary (msgpack) serialize/unserialize

2017-06-28 Thread Rasmus Schultz
Back in 2014 there was an informal proposal on the mailing list to replace
PHP serialization with an efficient binary (msgpack) format.

https://www.mail-archive.com/internals@lists.php.net/msg69870.html

As argued back then, breaking serialize() and unserialize() is unacceptable
for many reasons.

Meanwhile, the default session-storage, third-party cache libraries, etc.
continue to use serialize() and unserialize() with better options being
available only outside of the standard PHP run-times.

Why don't we either:

1. adopt msg_pack() and msg_unpack() from the PECL package as standard
functions, or

2. add a new pair of functions, e.g. bin_serialize() and bin_unserialize()
to supersede the existing functions

Or possibly both - that is, alias the pack/unpack functions with names
indicating they supersede the old un/serialize functions, but document the
new bin_* functions are using "an unspecified internal format". This way,
people can elect to use msgpack binary format now and in the future, or
elect to use msgpack now and possibly a different format in the future.

Optionally the bin_* functions could lead with a version byte (or maybe a
4-byte header) allowing backwards compatibility with future binary formats.
This way we don't risk ending up in the same situation again in 10 years if
we realize msgpack is bad for serialization for any reason.

There are many other uses for a set of efficient (space and time)
un/serialization functions, for example when packing small payloads
(checksums, image dimensions, etc.) into URLs, when persisting data in
cookies, etc.

Thoughts?


Re: [PHP-DEV] [RFC]Discuss] Syntax for Arrow Functions

2017-06-23 Thread Rasmus Schultz
I think there is not much point in carrying on this debate.

Suffice it to say, I understand your arguments and your point of view, I
just don't agree with it - if this new feature produces closures, by my
understanding, it's alternate syntax for producing closures, and does not
constitute a new language feature, but rather an alternative to an existing
feature.

I'm a big non-believer in syntax alternatives for the same
language-features for various use-cases - picking between cosmetic options
slows me down while programming. I prefer languages that are consistent, in
the sense that each feature has a consistent syntax that works for every
use-case - and as such I would be happy with an improved syntax that fully
replaces the old syntax and works better for every use-case, but I would
view specialized alternate syntax, for the same feature, for certain
specific use-cases, as merely inconsistency and a symptom of missing
design. I admire languages with little, consistent syntax and
widely-applicable, highly-generalized features.

I understand if not everyone shares my point of view.


On Wed, Jun 21, 2017 at 11:19 PM, Rowan Collins <rowan.coll...@gmail.com>
wrote:

> On 21/06/2017 15:04, Rasmus Schultz wrote:
> > > For me (and I am not alone), this feature is NOT a new syntax for
> closures
> >
> > Regardless of why you want it, that's exactly what it is though -
> another way to declare a closure.
> >
> > Even if it has different semantics, the resulting object is still an
> instance of Closure, right?
> >
> > It should pass type-checks, it should support reflection, and so on -
> otherwise, that's even more inconsistency,
> > for no practical reason, and it will lead to an endless list of problems
> which people will solve with even more ugly work-arounds,
> > such as omitting type-hints, etc.
>
> I am perfectly happy for the feature to support all those things.
>
>
> > > If what you are looking for is a replacement syntax for existing
> closures, you will have a completely different set of priorities
> >
> > I am not looking for a replacement syntax, but rather a replacement
> feature.
>
> Then you are looking for something different from me. Again, I don't say
> you are wrong in this, I just don't share that desire, because I don't see
> the need to replace - or supplement - a working feature with a slightly
> different version.
>
>
> > I think the priorities and requirements remain the same, but for
> consistency, and to keep this feature generally useful,
> > this feature should have parity with current Closures in terms of
> capabilities - otherwise it will get in the way rather than help.
>
> Again, this makes sense only given your starting point, which is not the
> same as mine.
>
>
> > Once people see the nicer, shorter syntax, and start to enjoy the more
> natural scoping rules, it's going to be
> > very frustrating to have to back-port to the old function-syntax and add
> use-clauses etc every time the code
> > changes and a single expression doesn't cut it.
>
> I mentioned this in my last e-mail without going into details, because it
> was discussed at length in the past, but perhaps you missed that, or have
> forgotten. In PHP, automatic capture of variables is absolutely not a
> natural scoping rule. Apart from the request super-globals - which many
> modern frameworks deliberately hide away from the user - every single
> variable has to be explicitly declared or imported into every single scope,
> throughout the entire language.
>
> The "use" clause on anonymous functions is not some weird wart for
> implementation purposes, it is the natural companion to the "global" and
> "static" keywords, and the natural consequence of not having a declaration
> to force a variable to be local. In PHP, all variables are local to a
> function by default, unless something explicitly says otherwise; there are
> certainly languages, notably JS, where the opposite is true, but that
> doesn't mean PHP is doing it wrong, or that mixing the two conventions in
> one language would be a good idea.
>
> I am willing to accept single-expression lambdas as an exception to this
> rule only because they are constrained to be short and simple; they read
> like an expression embedded in the outer scope, not a complete function in
> their own right.
>
>
> > A single-expression constraint on this feature would be a strange,
> arbitrary, annoying, unnecessary limitation.
> >
> > We didn't get it right the first time.
>
> I disagree with both of these statements. I don't consider this feature an
> attempt to fix something that went wrong, I consider it a new,
> complimentary, feature,

Re: [PHP-DEV] [RFC]Discuss] Syntax for Arrow Functions

2017-06-21 Thread Rasmus Schultz
> Once you start getting into multi statement closures, all the weird
syntax elements that are being proposed just make it harder to read and
harder to visually parse.

The same is true for current function syntax. But that's what line-breaks
are for :-)

> Automatically importing variables isn’t “more natural”, unless you think
JavaScript is god’s gift to programmers.

Meh, but it's what web developers are used to.

The two biggest web languages, PHP and JS, you know?

Most other languages don't require you to explicitly import vars into
closures either.


On Wed, Jun 21, 2017 at 5:19 PM, Stephen Reay <step...@bobs-bits.com> wrote:

>
> > On 21 Jun 2017, at 21:04, Rasmus Schultz <ras...@mindplay.dk> wrote:
> >
> > Once people see the nicer, shorter syntax,
>
> For anything but the most basic of closures, the shorter syntax just makes
> it harder to visually identify the logic. For 1 liners like `fn($x) => $x *
> 2` I can agree there is an argument that its easier to read. I don’t
> necessarily agree but I can agree there is an argument to be made.
>
> Once you start getting into multi statement closures, all the weird syntax
> elements that are being proposed just make it harder to read and harder to
> visually parse.
>
>
> > and start to enjoy the more
> > natural scoping rules,
>
> Automatically importing variables isn’t “more natural”, unless you think
> JavaScript is god’s gift to programmers.
>
>


Re: [PHP-DEV] [RFC]Discuss] Syntax for Arrow Functions

2017-06-21 Thread Rasmus Schultz
> For me (and I am not alone), this feature is NOT a new syntax for closures

Regardless of why you want it, that's exactly what it is though - another
way to declare a closure.

Even if it has different semantics, the resulting object is still an
instance of Closure, right?

It should pass type-checks, it should support reflection, and so on -
otherwise, that's even more inconsistency, for no practical reason, and it
will lead to an endless list of problems which people will solve with even
more ugly work-arounds, such as omitting type-hints, etc.

> If what you are looking for is a replacement syntax for existing
closures, you will have a completely different set of priorities

I am not looking for a replacement syntax, but rather a replacement feature.

I think the priorities and requirements remain the same, but for
consistency, and to keep this feature generally useful, this feature should
have parity with current Closures in terms of capabilities - otherwise it
will get in the way rather than help.

Once people see the nicer, shorter syntax, and start to enjoy the more
natural scoping rules, it's going to be very frustrating to have to
back-port to the old function-syntax and add use-clauses etc every time the
code changes and a single expression doesn't cut it.

A single-expression constraint on this feature would be a strange,
arbitrary, annoying, unnecessary limitation.

We didn't get it right the first time. Let's get it right this time, not
just adding another feature as a work-around to certain specific cases.

We have closures - no matter how you view it or describe it, regardless of
why you want this feature, this is another way to create closures, and it
needs to have parity with the existing feature.

Unless you're saying these are an entirely new type of object that isn't an
instance of Closure, in which case I'd say this whole feature is guaranteed
to do considerably more harm than good?


On Tue, Jun 20, 2017 at 7:52 PM, Rowan Collins <rowan.coll...@gmail.com>
wrote:

> On 19 June 2017 21:22:53 BST, Rasmus Schultz <ras...@mindplay.dk> wrote:
> >So what's on the table is a syntax-improved but feature-crippled
> >variant of
> >closures, not an all-round replacement?
>
> I haven't the time right now to dig out my summary from the mail archives,
> but this is one of the fundamental disagreements / misunderstandings that
> made discussion difficult the first time: different people want very
> different things from this feature, leading to conflicting views on whether
> certain things are advantages or disadvantages.
>
> For me (and I am not alone), this feature is NOT a new syntax for
> closures. It is a new TYPE of closure, with new semantics - automatically
> capturing variables - for a specific use case.
>
> Personally, I am strongly opposed to any multi-line version of it, because
> I don't want the fundamental scoping rules of the language changed except
> for the specific case of simple lambda expressions.
>
> If what you are looking for is a replacement syntax for existing closures,
> you will have a completely different set of priorities. That doesn't make
> either of us wrong, but it does mean we're going to find it very hard to
> agree on a syntax and feature set.
>
> Regards,
>
> --
> Rowan Collins
> [IMSoP]
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] [RFC]Discuss] Syntax for Arrow Functions

2017-06-20 Thread Rasmus Schultz
> I just think your example is an exaggeration to what happens in practice.

I think it's an example of what happens with any inconsistent feature in
any language.


On Tue, Jun 20, 2017 at 9:53 AM, Markus Fischer <mar...@fischer.name> wrote:

> Hello Rasmus,
>
> On 19.06.17 22:22, Rasmus Schultz wrote:
>
>> If I have to factor back and forth between new and old syntax every time a
>> closure changes from one to multiple or back to one statement, then,
>> frankly, what's the point?
>>
>> I think I would just keep using the old syntax, then - for consistency,
>> and
>> to save myself the frustration of factoring back and forth.
>>
>
> I'm writing closures every day and it's so rare to have this changes from
> single/multiple I don't even remember. I think in practice this is a
> non-issue except for very rare special cases and, don't forget: it's
> optional, you don't have to.
>
> In my opinion, if this is worth doing, it's worth doing it right.
>>
>
> No counter-argument here :)
>
> I just think your example is an exaggeration to what happens in practice.
>
> - Markus
>
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] [RFC]Discuss] Syntax for Arrow Functions

2017-06-19 Thread Rasmus Schultz
So what's on the table is a syntax-improved but feature-crippled variant of
closures, not an all-round replacement?

If I have to factor back and forth between new and old syntax every time a
closure changes from one to multiple or back to one statement, then,
frankly, what's the point?

I think I would just keep using the old syntax, then - for consistency, and
to save myself the frustration of factoring back and forth.

The old syntax is a burden, but a new feature with limited applicability,
honestly, I think would be even more of a burden.

In my opinion, if this is worth doing, it's worth doing it right.


On Mon, Jun 19, 2017 at 10:12 PM, Larry Garfield <la...@garfieldtech.com>
wrote:

>
>
> On 06/19/2017 03:45 PM, Rasmus Schultz wrote:
>
>> Or maybe it'll look okay if you format the code?
>>
>>  $things->forEach({$v => {
>>  foo($v);
>>  bar($v);
>>  }});
>>
>> Still looks kinda crazy with the closing "}})" though...
>>
>
> Multi-line lambdas should use the existing syntax without changes. The
> only thing being discussed here is single-statement lambdas that you would
> want to inline and think of as an expression rather than a function call.
> If you need something more complex than that just use the existing syntax.
>
> --Larry Garfield
>
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] [RFC]Discuss] Syntax for Arrow Functions

2017-06-19 Thread Rasmus Schultz
Or maybe it'll look okay if you format the code?

$things->forEach({$v => {
foo($v);
bar($v);
}});

Still looks kinda crazy with the closing "}})" though...


On Mon, Jun 19, 2017 at 9:43 PM, Rasmus Schultz <ras...@mindplay.dk> wrote:

> I actually like this syntax, but what would it look like for
> multi-statement closures?
>
> A nested set of curly braces around the body would look pretty messy.
>
> $things->forEach({$v => { foo($v); bar($v); }});
>
>
> On Mon, Jun 19, 2017 at 4:43 PM, Levi Morrison <le...@php.net> wrote:
>
>> On Sun, Jun 18, 2017 at 1:44 PM, Ilija Tovilo <ilija.tov...@me.com>
>> wrote:
>> > Sorry, I wasn’t aware of that.
>> >
>> > What do you think of the Ruby/Rust style syntax that Levi proposed a
>> while back?
>> >
>> > $someDict
>> > ->map(|$v| $v * 2)
>> > ->filter(|$v| $v % 3);
>> >
>> > This one has a few advantages:
>> >
>> > 1. It has syntax (a lot of) developers are already familiar with
>> > 2. It has no ambiguities and is fully backward compatible
>> > 3. It’s the shortest of all options available (two `|` characters and
>> one space)
>>
>> We determined that the arrow between the parameters and the expression
>> would still be required. Given this limitation I think this syntax is
>> seviceable:
>>
>> $someDict
>> ->map({$v => $v * 2})
>> ->filter({$v => $v % 3});
>>
>> Sometime this week I intend to start another thread that narrows us
>> down to two choices.
>>
>
>


Re: [PHP-DEV] [RFC]Discuss] Syntax for Arrow Functions

2017-06-19 Thread Rasmus Schultz
I actually like this syntax, but what would it look like for
multi-statement closures?

A nested set of curly braces around the body would look pretty messy.

$things->forEach({$v => { foo($v); bar($v); }});


On Mon, Jun 19, 2017 at 4:43 PM, Levi Morrison  wrote:

> On Sun, Jun 18, 2017 at 1:44 PM, Ilija Tovilo  wrote:
> > Sorry, I wasn’t aware of that.
> >
> > What do you think of the Ruby/Rust style syntax that Levi proposed a
> while back?
> >
> > $someDict
> > ->map(|$v| $v * 2)
> > ->filter(|$v| $v % 3);
> >
> > This one has a few advantages:
> >
> > 1. It has syntax (a lot of) developers are already familiar with
> > 2. It has no ambiguities and is fully backward compatible
> > 3. It’s the shortest of all options available (two `|` characters and
> one space)
>
> We determined that the arrow between the parameters and the expression
> would still be required. Given this limitation I think this syntax is
> seviceable:
>
> $someDict
> ->map({$v => $v * 2})
> ->filter({$v => $v % 3});
>
> Sometime this week I intend to start another thread that narrows us
> down to two choices.
>


Re: [PHP-DEV] [RFC]Discuss] Syntax for Arrow Functions

2017-06-18 Thread Rasmus Schultz
I understand it's not ambiguous to the parser if it's a keyword.

I was referring to the visual ambiguity - the fn($x) part of the syntax is
indistinguishable from a function-call.


On Sun, Jun 18, 2017 at 8:42 PM, Ilija Tovilo <ilija.tov...@me.com> wrote:

> > I don't agree that the fn keyword solves the ambiguity problem - it looks
> > exactly like a function call.
>
>
> Right. But it does solve the ambiguity if `fn` is a keyword which is what
> the RFC suggests.
>
>
> > On 18 Jun 2017, at 18:40, Rasmus Schultz <ras...@mindplay.dk> wrote:
> >
> > I don't agree that the fn keyword solves the ambiguity problem - it looks
> > exactly like a function call.
> >
> > As for the backslash, my honest reaction is, ugh, please, no more
> > backslashes - PHP (and every other language) uses backslashes for
> escaping
> > in strings, it already looks pretty awkward in namespaces, this won't
> help.
> >
> >
> > On Sun, Jun 18, 2017 at 12:58 PM, Ilija Tovilo <ilija.tov...@me.com>
> wrote:
> >
> >> The backslash has actually been one of the earlier options if I remember
> >> correctly.
> >> I definitely prefer the `fn` keyword as it’s only one character more but
> >> adds a better visual hint to the arrow function.
> >>
> >> I’m also not sure why we’d choose a different arrow (`==>` or `~>`) when
> >> the ambiguity is solved through either a the backslash or the `fn`
> keyword.
> >>
> >>
> >>> On 15 Jun 2017, at 17:00, Björn Larsson <bjorn.x.lars...@telia.com>
> >> wrote:
> >>>
> >>> Den 2017-06-15 kl. 15:34, skrev Fleshgrinder:
> >>>
> >>>> On 6/15/2017 3:29 PM, Björn Larsson wrote:
> >>>>> Seems like the constraints on this feature makes it hard to fly, i.e.
> >>>>> 1. Not a hackish implementation
> >>>>> 2. Non ambiguous syntax
> >>>>> 3. Easy to parse & use syntax for the human
> >>>>>
> >>>>> HackLang then prioritised 2 & 3 making the end-users happy, but
> >>>>> had to sacrifise a clean implementation. Any clue if this was a one-
> >>>>> time effort once it was done or something with a lot of drawbacks
> >>>>> in terms of maintenance, performance, evolution etc?
> >>>>>
> >>>>> r//Björn
> >>>>>
> >>>> On Reddit someone proposed the following syntax:
> >>>>
> >>>>\() => echo 'Hello, World'
> >>>>
> >>>> It is used by Haskell if I remember correctly and should not be
> >>>> ambiguous since `(` is not allowed in names of classes or functions.
> It
> >>>> actually aligns well with functions that are called with a
> >>>> fully-qualified name (e.g. `\printf('')`).
> >>>>
> >>>> Not sure if it would still require hacks though.
> >>>>
> >>> So applying that one on Sara's example becomes with some
> >>> options for the arrow:
> >>> 8. $someDict->map(\($v) => $v * 2)->filter(\($v) => $v % 3);
> >>> 9. $someDict->map(\($v) ==> $v * 2)->filter(\($v) ==> $v % 3);
> >>> 10. $someDict->map(\($v) ~> $v * 2)->filter(\($v) ~> $v % 3);
> >>>
> >>> Interesting :)
> >>>
> >>> r//Björn
> >>>
> >>> --
> >>> PHP Internals - PHP Runtime Development Mailing List
> >>> To unsubscribe, visit: http://www.php.net/unsub.php <
> >> http://www.php.net/unsub.php>
> >>
>
>


Re: [PHP-DEV] [RFC]Discuss] Syntax for Arrow Functions

2017-06-18 Thread Rasmus Schultz
I don't agree that the fn keyword solves the ambiguity problem - it looks
exactly like a function call.

As for the backslash, my honest reaction is, ugh, please, no more
backslashes - PHP (and every other language) uses backslashes for escaping
in strings, it already looks pretty awkward in namespaces, this won't help.


On Sun, Jun 18, 2017 at 12:58 PM, Ilija Tovilo  wrote:

> The backslash has actually been one of the earlier options if I remember
> correctly.
> I definitely prefer the `fn` keyword as it’s only one character more but
> adds a better visual hint to the arrow function.
>
> I’m also not sure why we’d choose a different arrow (`==>` or `~>`) when
> the ambiguity is solved through either a the backslash or the `fn` keyword.
>
>
> > On 15 Jun 2017, at 17:00, Björn Larsson 
> wrote:
> >
> > Den 2017-06-15 kl. 15:34, skrev Fleshgrinder:
> >
> >> On 6/15/2017 3:29 PM, Björn Larsson wrote:
> >>> Seems like the constraints on this feature makes it hard to fly, i.e.
> >>> 1. Not a hackish implementation
> >>> 2. Non ambiguous syntax
> >>> 3. Easy to parse & use syntax for the human
> >>>
> >>> HackLang then prioritised 2 & 3 making the end-users happy, but
> >>> had to sacrifise a clean implementation. Any clue if this was a one-
> >>> time effort once it was done or something with a lot of drawbacks
> >>> in terms of maintenance, performance, evolution etc?
> >>>
> >>> r//Björn
> >>>
> >> On Reddit someone proposed the following syntax:
> >>
> >> \() => echo 'Hello, World'
> >>
> >> It is used by Haskell if I remember correctly and should not be
> >> ambiguous since `(` is not allowed in names of classes or functions. It
> >> actually aligns well with functions that are called with a
> >> fully-qualified name (e.g. `\printf('')`).
> >>
> >> Not sure if it would still require hacks though.
> >>
> > So applying that one on Sara's example becomes with some
> > options for the arrow:
> > 8. $someDict->map(\($v) => $v * 2)->filter(\($v) => $v % 3);
> > 9. $someDict->map(\($v) ==> $v * 2)->filter(\($v) ==> $v % 3);
> > 10. $someDict->map(\($v) ~> $v * 2)->filter(\($v) ~> $v % 3);
> >
> > Interesting :)
> >
> > r//Björn
> >
> > --
> > PHP Internals - PHP Runtime Development Mailing List
> > To unsubscribe, visit: http://www.php.net/unsub.php <
> http://www.php.net/unsub.php>
>


Re: [PHP-DEV] [RFC]Discuss] Syntax for Arrow Functions

2017-06-08 Thread Rasmus Schultz
> it could be a single symbol instead of two

even if this can be done without parser ambiguity, it suffers from visual
ambiguity with the assignment operator.

consider what this would look like if the expression itself uses the
assignment operator...

f($x) = $y = $y + $x;

versus something like:

f($x) => $y = $y + $x;

even that is visually ambiguous when used in arrays though:

$a = [
"foo" => f($x) => $y = $y + $x,
];

also unreadable.

even if the parser can cope, I think we need some other symbol that isn't
visually ambiguous when used in these contexts?


On Thu, Jun 8, 2017 at 5:56 PM, Fleshgrinder <p...@fleshgrinder.com> wrote:

> On 6/7/2017 9:45 PM, Rasmus Schultz wrote:
> >> the `fn($a, $b) => $a + $b ** $c` syntax suddenly becomes an acceptable
> > compromise.
> >
> > I have to second that.
> >
> > I might even propose to shorten it from "fn" to just "f" - the resulting
> > syntax then resembles a mathematical predicate :-)
> >
>
> I really like your thinking here. +1 for just `f`.
>
> I am not sure why we would require the fat arrow anymore. We most
> probably want some symbol there to separate the return type constraint
> from the body, but it could be a single symbol instead of two:
>
> f($x) = $x^3
> f(int $x): int = $x^3
>
> We could go full math here! :)
>
> --
> Richard "Fleshgrinder" Fussenegger
>
>


Re: [PHP-DEV] preg_match() option for anchored offset?

2017-06-08 Thread Rasmus Schultz
> You are looking for the \G anchor or the A modifier.

Both of these options work great!

I've submitted a patch to the manual page with a note explaining these
options.

Thanks :-)


On Wed, Jun 7, 2017 at 10:13 PM, Nikita Popov <nikita@gmail.com> wrote:

> On Wed, Jun 7, 2017 at 10:03 PM, Rasmus Schultz <ras...@mindplay.dk>
> wrote:
>
>> What do you think about adding another option to preg_match() to allow the
>> $offset parameter to be treated as the start anchor?
>>
>> The manual proposes to do this:
>>
>> $subject = "abcdef";
>> $pattern = '/^def/';
>> $offset = 3;
>> preg_match($pattern, substr($subject, $offset), $matches);
>>
>> In other words, use substr() to copy the entire remainder of the string.
>>
>> I just wrote a simple SQL parser tonight, and had to use this approach,
>> which (I imagine) must be pretty inefficient?
>>
>> I'd like to be able to do the following:
>>
>> $subject = "abcdef";
>> $pattern = '/^def/';
>> $offset = 3;
>> preg_match($pattern, $subject, $matches, PREG_ANCHOR_OFFSET, $offset);
>>
>> This new option would make the ^ anchor work from the given $offset, which
>> allows me to parse the entire $subject without copying anything.
>>
>> Thoughts?
>>
>
> You are looking for the \G anchor or the A modifier.
>
> Nikita
>
>


[PHP-DEV] preg_match() option for anchored offset?

2017-06-07 Thread Rasmus Schultz
What do you think about adding another option to preg_match() to allow the
$offset parameter to be treated as the start anchor?

The manual proposes to do this:

$subject = "abcdef";
$pattern = '/^def/';
$offset = 3;
preg_match($pattern, substr($subject, $offset), $matches);

In other words, use substr() to copy the entire remainder of the string.

I just wrote a simple SQL parser tonight, and had to use this approach,
which (I imagine) must be pretty inefficient?

I'd like to be able to do the following:

$subject = "abcdef";
$pattern = '/^def/';
$offset = 3;
preg_match($pattern, $subject, $matches, PREG_ANCHOR_OFFSET, $offset);

This new option would make the ^ anchor work from the given $offset, which
allows me to parse the entire $subject without copying anything.

Thoughts?


Re: [PHP-DEV] [RFC]Discuss] Syntax for Arrow Functions

2017-06-07 Thread Rasmus Schultz
> the `fn($a, $b) => $a + $b ** $c` syntax suddenly becomes an acceptable
compromise.

I have to second that.

I might even propose to shorten it from "fn" to just "f" - the resulting
syntax then resembles a mathematical predicate :-)


On Wed, Jun 7, 2017 at 5:20 PM, Stephen Reay 
wrote:

>
> > On 7 Jun 2017, at 20:37, Björn Larsson 
> wrote:
> >
> > Well, one reason to use fn or even lambda was to signal that this is
> > different then a regular function.
> >
> > When it comes to number of keystrokes I guess that some inspiration
> > has been taken from other languages supporting arrow functions, like
> > Javascript & HACK.
> >
> > I also recall from earlier discussions, that with less keystrokes it's
> easier
> > to read when an arrow function is embedded / chained into another
> > expression / statement / function call.
> >
>
>
> I think its pretty clear my pref is/was #2, but when compared to the crazy
> alternatives people have been suggesting, which just seem to be “hold down
> shift and blindly poke at the non-letter keys for a while”, the `fn($a, $b)
> => $a + $b ** $c` syntax suddenly becomes an acceptable compromise.
>
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] [RFC]Discuss] Syntax for Arrow Functions

2017-06-05 Thread Rasmus Schultz
Ugh, you're right, that's totally unreadable... the => is far too ambiguous
with array syntax, I agree.

How about just a thin arrow?

(params) -> expr

If the parens around params were required, it's not ambiguous with the
trailing -- operator, is it?

$foo->bar(($baz) -> $baz + 1);

Consistent use of parens around the params might make closures a bit easier
to spot in the wild?


On Mon, Jun 5, 2017 at 8:11 PM, Björn Larsson 
wrote:

>
>
> Den 2017-06-05 kl. 19:55, skrev Rowan Collins:
>
>> On 5 June 2017 18:17:06 BST, Fleshgrinder  wrote:
>>
>>> Could someone explain me again what the problem with the simple
>>> fat-arrow and normal parenthesis is? Cannot find it anymore (too many
>>> messages in too many thread I guess). I would guess that it has to do
>>> with the arbitrary look-ahead that is required to check for the fat
>>> arrow before the lexer knows that this is a short closure and not some
>>> parenthesis that simply groups something.
>>>
>> I think it's not just a case of implementation problems, it's actually
>> ambiguous with current syntax:
>>
>> $foo = array( ($x) => 42 );
>>
>> Sure, those inner brackets are redundant, so it's not likely to break
>> much actual code, but it's kind of weird to have this one case magically
>> turn into a closure, when anything else you put in those brackets would
>> just be used as the array key:
>>
>> $foo = array( f($x) => 42 );
>> $foo = array( ($x+1) => 42 );
>> $foo = array( (42) => $x );
>> $foo = array( (X) => 42 );
>> $foo = array( ($x) => 42 );
>> $foo = array( ("$x") => 42 );
>>
>> Even if we could teach the parser to understand it, I'd personally be
>> against it for the difficulty of *humans* parsing it. I find shorthand
>> closures hard enough to read anyway, especially when people suggest things
>> like ($x) => ($y) => $x * $y * $z;
>>
>> Regards,
>>
>> +1, think you nailed it here :) One of the reasons I prefer the ==>
> syntax.
>
> r//Björn
>
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] [RFC]Discuss] Syntax for Arrow Functions

2017-06-05 Thread Rasmus Schultz
Of the proposed options, I'd prefer the double fat-arrow ==>

However, I remain of the opinion that all of those syntaxes are
work-arounds to ambiguity concerns for cases that likely don't actually
occur in real-world codebases.

I don't understand the motivation to design or optimize based on some
theoretical concerns - I'd strongly prefer we do the obvious thing, which,
as I see it, would be to do what most languages do, e.g. the familiar fat
arrow => syntax.

If we're going to provide a closure feature that works more like what you'd
typically find in other languages, we should try to also make it look like
it does in most other languages.

It was said of the generics syntax that I proposed that it would have
ambiguity issues, that it would be impossible (or very difficult) to
implement, but someone actually went an implemented it. I'm generally a bit
skeptical of people who cry "impossible" before giving it their best effort.

Inventing unfamiliar syntax for familiar features should be a painful last
resort, if there is no other choice.

Just my opinion.

I'd love to have this feature, but I'd prefer we don't introduce anymore
"muck" if it's at all avoidable.


On Mon, Jun 5, 2017 at 3:10 PM, Björn Larsson 
wrote:

> Den 2017-06-01 kl. 18:58, skrev Theodore Brown:
>
> On Tuesday, May 30, 2017 at 12:58 PM, Levi Morrison wrote:
>>
>> Based on the discussion there are a few different syntax choices
>>> people liked. Overall it's a feature that people seem to want but
>>> everyone seems to prefer a different syntax choice.
>>>
>>> 1. fn(params) => expr
>>> 2. function(params) => expr
>>> 3. (params) ==> expr
>>> 4. (params) => expr
>>> 5.
>>> [](params) => expr // binds no values
>>> [=](params) => expr // binds by value
>>> [&](params) => expr // binds by reference
>>>
>> As a userland developer, I've been waiting/hoping for short arrow
>> functions for a long time!
>>
>> Option 3 seems like the most obvious choice, since that's the
>> same syntax Hack uses. Would it be very difficult to implement the
>> parser changes necessary for this syntax? Or is there some other
>> downside to a more powerful grammar/parser (e.g. worse performance)?
>>
>> If option 3 isn't viable, my next preference would be option 1.
>> Presumably the drawback of a new symbol is that it might break
>> existing code using `fn` as the name of a class or function.
>> However, using a new symbol would arguably enable more readable
>> code than the other options.
>>
>> Option 2 is not only lengthy, but it also could be confusing
>> since it reuses the `function` symbol for something that isn't
>> a normal function.
>>
>> Option 5 seems overly complex and hard to read.
>>
>> Whether option 1, 2, or 3 is used, to me it seems that capturing by
>> reference would be the most useful and intuitive behavior. It's
>> intuitive since implicit capture makes it feel like all the captured
>> variables are in the same scope.
>>
>
> As a user land developer, option 3 is also my favourite followed by 5 and
> last 1.
>
> However, for option 5 I would prefer ==> syntax and for option 1 I would
> prefer
> lambda as a keyword instead of fn.
>
> One thought that struck me, would option 3 be possible to extend also
> including
> option 5 either as a voting option or in a future RFC?
>
> And yes, arrow functions is much welcome!
>
> r//Björn
>
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] Parameter type widening RFC

2017-05-30 Thread Rasmus Schultz
> The type widening RFC makes it easier to move to parameter types for
existing libraries.

I'm curious to see how you'll set the version constraint in your
composer.json file.

After adding a scalar type-hint to an interface, which is a breaking change
in 7.0 and 7.1, but a non-breaking change in 7.2, is the new version of
your package a major or minor release?

If you release it as minor, you'll need a PHP version constraint like
"^5.5, ^7.2", but excluding 7.0-7.1 In that way is itself a breaking
change, so likely your only practical move is to release (and commit to
maintain!) both major and minor versions, which doesn't sound easy at all.


On May 29, 2017 00:53, "Dan Ackroyd" <dan...@basereality.com> wrote:

> On 28 May 2017 at 14:25, Rasmus Schultz <ras...@mindplay.dk> wrote:
> >
> > To me, that's a setback that leads to harder-to-debug errors, and
> increases
> > learning-curve.
>
> Everything is a trade-off. The type widening RFC makes it easier to
> move to parameter types for existing libraries.
>
> While I can see what you mean about how it could lead to more
> accidental errors, for me at least, it would be actually quite hard to
> not notice those errors in the code.
>
> First, when people are programming against the interface rather than
> the implementation, that type of mistake is much easier to spot.
>
> function foo(Repository $repo) {
> $repo->save(new stdClass());
> // The above line is marked as an error in any decent IDE
> // or code analysis tool.
> }
>
> Second, accidentally dropping the type from the parameter is also an
> easy mistake to spot.
>
> class UserRepository implements Repository {
> public function save($item) {
> // When inside this function the programmer has no idea
> // what type item is. Any call to a method or property will
> // be marked as a potential error either by an IDE, static
> // analysis tool, or just the programmer realising
> // "that parameter has no type".
> }
> }
>
> So, to me (and possibly others who voted for the RFC) the ability to
> add types to interfaces without breaking implementing library is a
> good trade-off.
>
> And yes, the type system in PHP could definitely be improved. Perhaps
> you could propose an RFC? I suspect it might need to target PHP 8. I'm
> personally hoping that some form of the union type RFC could return,
> though possibly in a more general form.
>
> cheers
> Dan
> Ack
>


Re: [PHP-DEV] Parameter type widening RFC

2017-05-28 Thread Rasmus Schultz
Alright, here's an example of code where a type-hint was accidentally left
out.

Before this change:

https://gist.github.com/mindplay-dk/e988902ed2d587dc05a1d8cb164b88c4/4d03babff16883a67accfb51b50e3d1aefb13a8a

And after this change:

https://gist.github.com/mindplay-dk/e988902ed2d587dc05a1d8cb164b88c4/03a4eec05b64185830785c5e684b3f94c1d62f5e

In other words, accidental omission of type-hints now means that this
faulty implementation is valid code.

And hopefully something will error, deep inside a call-stack, maybe in a
database-component that performs a type-check or something, but there is no
guarantee that it will error at all - if you passed an object that does
have a getID() method, because there's actually no type-check for the
Identity interface when calling the implementation, worst case, it actually
executes and quietly saves *something* to the database.

> No, interfaces exist to guarantee the caller can always pass a type XY
there.
> With type constraints removed in a subclass, this guarantee does not
break.

No, but you no longer get a type-check.

So yes, for *correct* code, there is no problem - but if you didn't write
the code correctly the first time, with this change, you may never even
know you've done something wrong, or you may have to drill through a much
larger call-stack and try to derive the source of the problem.

Before this change, a faulty implementation would simply get rejected.

To me, that's a setback that leads to harder-to-debug errors, and increases
learning-curve.

With an explicit mixed type-hint, you can still achieve what you want in
those rare cases where this simplified kind of contravariance is actually
useful, without also creating new problem cases for everyday coding.


On Sun, May 28, 2017 at 2:27 PM, Niklas Keller <m...@kelunik.com> wrote:

> 2017-05-28 12:30 GMT+02:00 Rasmus Schultz <ras...@mindplay.dk>:
>
>> > > So this breaks the expected behavior of interfaces.
>> >
>> > No it doesn't. It allows interfaces to use contravariance within PHP's
>> > type system, which is different from before, but it doesn't break
>> > anything.
>>
>> The RFC explicitly states that this is *not* contravariance.
>>
>
> Where does it state that? (The "true" in the future scope section should
> probably be replaced with "full".)
>
>
>> And if it's not clear, what I mean by "breaks the expected behavior", is,
>> as far as I understand, what this RFC actually does is it *removes*
>> expected behavior.
>>
>
> How does this *remove* expected behavior? Could you show a concrete
> example of code that breaks?
>
>
>> Correct me if I'm wrong, but really all this RFC does, is remove the
>> requirement that and implementation of an interface be type-hinted?
>>
>
> Correct, but not just for interfaces.
>
>
>> To me, that's "broken".
>>
>
> As said, please show a concrete example that breaks.
>
>
>> You're favorizing a very, very small number of isolated, valid use-cases -
>> by removing the normal, natural, expected constraint that an
>> implementation
>> be type-hinted as specified by the interface. It's part of the reason
>> interfaces even exist - and this simply ignores that and removes these
>> checks.
>>
>
> No, interfaces exist to guarantee the caller can always pass a type XY
> there. With type constraints removed in a subclass, this guarantee does not
> break.
>
>
>> In my opinion, this will very likely lead to a large number of accidental
>> type-hint omissions - and a very, very small number of actually useful
>> solutions to real problems.
>>
>> In my opinion, we can do much better than that, by adding a mixed
>> type-hint, which will ensure people aren't just accidentally omitting
>> type-hints and instead explicitly opting out of it to achieve parameter
>> widening. Solving this from the start also ensures we can have a clean
>> implementation of real contravariance in the future, without that being a
>> break change.
>
>
> You're, again, ignoring one of the major benefits of the RFC: Being able
> to move from explicit type checks to type declarations without breaking
> subclasses.
>
>
>> > Rasmus, not answering people's questions and instead saying emotional
>> > stuff suggesting other people have made historically bad decisions
>> > isn't a productive way to conduct a conversation.
>>
>> Okay, I'm emotional, sorry about that.
>>
>> But I think I'm pointing out a real problem and a real possible solution
>> that doesn't make the trade-offs of the current solution.
>>
>
> You haven't pointed out a real problem, yet.
>
> Regards, Niklas
>


Re: [PHP-DEV] Parameter type widening RFC

2017-05-28 Thread Rasmus Schultz
> > So this breaks the expected behavior of interfaces.
>
> No it doesn't. It allows interfaces to use contravariance within PHP's
> type system, which is different from before, but it doesn't break
> anything.

The RFC explicitly states that this is *not* contravariance.

And if it's not clear, what I mean by "breaks the expected behavior", is,
as far as I understand, what this RFC actually does is it *removes*
expected behavior.

Correct me if I'm wrong, but really all this RFC does, is remove the
requirement that and implementation of an interface be type-hinted?

To me, that's "broken".

You're favorizing a very, very small number of isolated, valid use-cases -
by removing the normal, natural, expected constraint that an implementation
be type-hinted as specified by the interface. It's part of the reason
interfaces even exist - and this simply ignores that and removes these
checks.

In my opinion, this will very likely lead to a large number of accidental
type-hint omissions - and a very, very small number of actually useful
solutions to real problems.

In my opinion, we can do much better than that, by adding a mixed
type-hint, which will ensure people aren't just accidentally omitting
type-hints and instead explicitly opting out of it to achieve parameter
widening. Solving this from the start also ensures we can have a clean
implementation of real contravariance in the future, without that being a
break change.

> Rasmus, not answering people's questions and instead saying emotional
> stuff suggesting other people have made historically bad decisions
> isn't a productive way to conduct a conversation.

Okay, I'm emotional, sorry about that.

But I think I'm pointing out a real problem and a real possible solution
that doesn't make the trade-offs of the current solution.

That is, I'm fine with introducing this simplified type of contravariance,
but I think it needs to be made explicit - simply omitting a type-hint does
not indicate the desired behavior; it doesn't indicate anything, and
thereby creates a new problem case of accidental type-hint omission.

Is there a very good reason we shouldn't address that, if it's at all
possible?


On Thu, May 25, 2017 at 12:32 PM, Dan Ackroyd <dan...@basereality.com>
wrote:

> On 25 May 2017 at 10:21, Rasmus Schultz <ras...@mindplay.dk> wrote:
>
> > So this breaks the expected behavior of interfaces.
>
> No it doesn't. It allows interfaces to use contravariance within PHP's
> type system, which is different from before, but it doesn't break
> anything.
>
> Niklas Keller wrote:
> > The interface will just work correctly, what's the actual problem you're
> seeing?
>
> Rasmus, not answering people's questions and instead saying emotional
> stuff suggesting other people have made historically bad decisions
> isn't a productive way to conduct a conversation.
>
> cheers
> Dan
>


Re: [PHP-DEV] Parameter type widening RFC

2017-05-25 Thread Rasmus Schultz
> > The feature, as implemented, will allow accidental omission of
type-hints,
> > will it not?
>
> Yes, correct.

So this breaks the expected behavior of interfaces.

This will be harmful to everyone, but especially harmful to new
programmers, who may never even learn how to correctly implement an
interface, since now they don't have to.

Promising to address this in a future version isn't helpful, as that would
be a BC break, which rarely anyone condones, even for major releases -
changing it now isn't a BC break, so it's easy, but fixing it will be a BC
break, which will be very hard to push through.

Addressing this by allowing developers to opt-in to proper interface
validation in strict mode isn't helpful either, and especially not to new
programmers who are likely much farther from learning about strict mode
than they are from learning about basic things like properly implementing
an interface - and much, much further from learning about parameter
type-hint widening.

IMO, this is likely to become another one of those historically bad design
decisions that were made in spite of everything we know about other
programming languages :-(


On Tue, May 23, 2017 at 10:46 PM, Niklas Keller  wrote:

> Hi Rasmus,
>
>
>> This parameter type widening RFC, I didn't know about, but I have a
>> remark.
>>
>> The feature, as implemented, will allow accidental omission of type-hints,
>> will it not?
>>
>
> Yes, correct.
>
>
>> Previously, the implements keyword guaranteed a correctly type-hinted
>> implementation - it's now possible to (purposefully, obviously, in certain
>> rare cases) omit type-hints by accident, making the implements keyword
>> much
>> less (or not any) of a guarantee that the interface is implemented
>> correctly.
>>
>
> The interface will just work correctly, what's the actual problem you're
> seeing?
>
>
>> The addition of an explicit "mixed" or "any" pseudo-type would have made
>> this possible, without losing the guarantee that the implements keyword
>> used to provide - that is, it would have been possible to have this
>> feature
>> for the few cases where it's useful, without affecting safety in the
>> majority of other cases where it's not.
>>
>> I feel like this feature takes a pretty dangerous shortcut by simply
>> removing a constraint check that we used to have - in favor of supporting
>> a
>> few rare cases, we removed a guarantee that interfaces and the
>> implements-keyword has always provided.
>>
>> Those rare cases could have been supported in a safe manner by introducing
>> a "mixed" or "any" type, which would have made the use of this feature
>> explicit - which would have removed the risk of accidental omission of
>> type-hints in the majority of cases.
>>
>
> Unfortunately, that doesn't work for the second (maybe even primary) use
> case of the RFC: Adding types to a class isn't a BC break anymore with the
> RFC, as child classes will just widen the type and need explicit checks as
> before. Without the RFC or with a version with "mixed" or "any", method
> signatures will be incompatible again and thus be a BC break when adding
> types to the base class.
>
> "mixed" has been mentioned in the original discussion, but there was not a
> lot of interest and mostly explicit disinterest.
>
>
>> The RFC page doesn't link to any discussion, and the Github thread was
>> shut
>> down after some negative remarks.
>>
>> I didn't see a discussion or a vote here on internals - did I miss
>> something? Where or how did this get discussed and passed? Are these
>> discussions happening somewhere else besides internals now?
>
>
>  - Original discussion: https://externals.io/thread/505
>  - Vote announcement: https://externals.io/thread/613
>  - Vote resumption after internals having issues: https://externals.io/
> thread/619
>
> Regards, Niklas
>


[PHP-DEV] Parameter type widening RFC

2017-05-23 Thread Rasmus Schultz
This parameter type widening RFC, I didn't know about, but I have a remark.

The feature, as implemented, will allow accidental omission of type-hints,
will it not?

Previously, the implements keyword guaranteed a correctly type-hinted
implementation - it's now possible to (purposefully, obviously, in certain
rare cases) omit type-hints by accident, making the implements keyword much
less (or not any) of a guarantee that the interface is implemented
correctly.

The addition of an explicit "mixed" or "any" pseudo-type would have made
this possible, without losing the guarantee that the implements keyword
used to provide - that is, it would have been possible to have this feature
for the few cases where it's useful, without affecting safety in the
majority of other cases where it's not.

I feel like this feature takes a pretty dangerous shortcut by simply
removing a constraint check that we used to have - in favor of supporting a
few rare cases, we removed a guarantee that interfaces and the
implements-keyword has always provided.

Those rare cases could have been supported in a safe manner by introducing
a "mixed" or "any" type, which would have made the use of this feature
explicit - which would have removed the risk of accidental omission of
type-hints in the majority of cases.

The RFC page doesn't link to any discussion, and the Github thread was shut
down after some negative remarks.

I didn't see a discussion or a vote here on internals - did I miss
something? Where or how did this get discussed and passed? Are these
discussions happening somewhere else besides internals now?


Re: [PHP-DEV] scalar type-casting

2017-04-10 Thread Rasmus Schultz
My concern is actually neither performance nor brevity - my concern is, can
you read the code and actually understand what it does, can you write code
without running into surprising side-effects, and so on.

DbC might have merit in terms of performance, but perhaps not so much in a
scripting language - if performance was critical to a given project, I
would not be using a scripting language. The addition of DbC and marginally
better performance for certain specific use-cases wouldn't change that for
me.


On Mon, Apr 10, 2017 at 4:04 AM, Yasuo Ohgaki <yohg...@ohgaki.net> wrote:

> Hi Rasmus,
>
> Although DbC is not what you need, but DbC could solve your issue
> more efficiently. i.e. Faster execution, not shorter code.
>
> https://wiki.php.net/rfc/dbc2
>
> With DbC, caller has responsibility to pass correct parameters.
>
> On Sun, Apr 9, 2017 at 6:30 PM, Rasmus Schultz <ras...@mindplay.dk> wrote:
>
>>
>> $one = "1";
>> $one_int = (int) $one;
>> add_one($one_int);
>>
>
>
> add_one(&$value)
>   require (is_int($value))
> {
>$value += 1;
> }
>
> // Caller has responsibility to pass correct parameters.
> $one = filter_validate($_GET['var'], FILTER_VALIDATE_INT);
> add_one($one);
>
>
>
>
>> class Foo { public function __toString() { return "foo"; } }
>> function append_to(string &$str) { $str .= "_bar"; }
>> $foo = new Foo();
>> append_to($foo);
>> var_dump($foo); // string(7) "foo_bar"
>
>
>
> class Foo { public function __toString() { return "foo"; } }
>
> function append_to(&$str)
>   require (is_string($str))
> {
>   $str .= "_bar";
> }
>
> $foo = new Foo();
>
> // Caller has responsibility to pass correct parameters, but it's not
> append_to($foo); // Error at DbC precondition check in append_foo()
> var_dump($foo); // Cannot reach here in dev mode
>
>
>
> I really like parameter type check.
> Problem is type check makes execution slower.
> Another problem is type check is not enough for many codes.
>
> With DbC support, we can specify any expressions. Therefore, we can
> check much more complex requirements for functions/methods at
> development time.
>
>
>
> e.g.
> function save_age($user_age)
>   require (is_int($user_age))
>   require ($user_age >= 0)
>   require ($user_age < 150)
> {
>save_to_somewehre($user_age);
> }
> //Note: All input parameters must be validated to be correct value for the
> app. e.g. use filter_validate()/etc
>
>
> What you really need might be DbC.
>
> Regards,
>
> --
> Yasuo Ohgaki
> yohg...@ohgaki.net
>
>


Re: [PHP-DEV] scalar type-casting

2017-04-09 Thread Rasmus Schultz
> If the caller sees only the signature, then the function can do
*literally anything* to their passed by reference variable. The caller is
giving full control and "ownership" of that variable, and shouldn't make
any assumptions about what it will look like when it comes back.

Understood, only this isn't the function doing something - it's the
language.

But I guess the best thing under any circumstances is to simply avoid using
references entirely - you won't have these problems then.

The main point was, I'd still very much like to see Anthony's RFC revived
:-)

So I guess this should be updated:

"when an internal function accepts a typed parameter by reference, if the
magic cast method is defined on the passed in object, an error is raised as
the cast cannot be performed because of the reference."

Perhaps to:

"when a function receives a type-hinted parameter by reference, if the
magic cast method is defined on the passed in object, the variable in the
calling scope is immediately overwritten with the result of the type-cast."

I don't happen to like it, but that's consistent with the existing
behavior, right?


On Sun, Apr 9, 2017 at 1:07 PM, Rowan Collins <rowan.coll...@gmail.com>
wrote:

> On 9 April 2017 10:30:02 BST, Rasmus Schultz <ras...@mindplay.dk> wrote:
> >Example:
> >
> >class Foo { public function __toString() { return "foo"; } }
> >function append_to(string &$str) { $str .= "_bar"; }
> >$foo = new Foo();
> >append_to($foo);
> >var_dump($foo); // string(7) "foo_bar"
> >
> >In this example, the caller's instance of Foo gets wiped out and
> >replaced
> >by a string
>
> While this looks surprising in the form you've written it, it should only
> really be a surprise to the function author, not the caller. If the caller
> sees only the signature, then the function can do *literally anything* to
> their passed by reference variable. The caller is giving full control and
> "ownership" of that variable, and shouldn't make any assumptions about what
> it will look like when it comes back.
>
> For example, you don't even need PHP7 to do this:
>
> class Foo { public function __toString() { return "foo"; } }
> function append_to(&$str) { $str = (string)$str . "_bar"; }
> $foo = new Foo();
> append_to($foo);
> var_dump($foo); // string(7) "foo_bar"
>
> I don't think it's any more unreasonable for a reference parameter to
> change type in the parameter handling of your example function (with
> strict_types off) than inside the body of my example function. Of course,
> by setting strict_types=1, the caller can change the implicit cast to an
> implicit assertion, and get an error in your example; it won't save them
> from my example, though.
>
> Regards,
>
> --
> Rowan Collins
> [IMSoP]
>


[PHP-DEV] scalar type-casting

2017-04-09 Thread Rasmus Schultz
Since PHP 7.0, I've started using scalar type-hints a lot, and it got me
thinking about scalar type-casting.

After poking through existing RFC's, it turns out, I was going to propose
precisely the thing that Anthony Ferrara proposed in 2012:

https://wiki.php.net/rfc/object_cast_to_types

In the light of scalar type-hints, I feel this RFC is now much more
relevant and useful than it was then.

One thing in this RFC jumps out at me though:

"when an internal function accepts a typed parameter by reference, if the
magic cast method is defined on the passed in object, an error is raised as
the cast cannot be performed because of the reference."

I'm afraid this is inconsistent with the behavior of built-in scalar
type-casts.

For example:

function add_one(int &$value) { $value += 1; }
$one = "1";
add_one($one);
var_dump($one); // int(2)

That is, an implicit type-cast made by passing e.g. a string to an int
reference argument has the side-effect of overwriting the input variable.

This behavior may be "okay" in the case of scalars, which, for the most
part, can just ping-pong between actual types - like, if someone were to
subsequently append to what they thought was a string in the above example,
the string-turned-integer would just convert itself back to a string.

The situation would be very different with an object being passed as
argument and cast to integer - if the object was simply replaced with an
integer as a side-effect, clearly this would have much more serious
ramifications than with scalars which can probably be cast back and forth
between various scalar types.

I'm guessing, at the time when scalar type-hints were introduced, you
likely weighed the pros and cons while designing this behavior and decided
it's "good enough", since it's damn near impossible to define another
rational behavior that is side-effect free and would also do something
meaningful with references (?)

It seems that references are once again the culprit that inspired "weird"
design-decisions such as side-effects.

I would call again for the deprecation/removal of references, but I know
that's a major language BC break and very unlikely to bear fruit, so I
won't suggest that.

Instead, I would like you to consider another, much smaller BC break, much
less likely to affect most code: rather than type-casting values when
passed by reference, instead type-check them, and error on mismatch.

That is, in the example above, add_one($one) would trigger an error,
because the variable you passed by reference isn't of the correct type.

I would need to refactor that code slightly, and introduce an intermediary
variable that is actually an integer, then call the function - or in other
words, I would need to write code that expresses what really happens, the
fact that the function operates on an integer variable in the calling scope:

$one = "1";
$one_int = (int) $one;
add_one($one_int);

This is much safer and much more transparent than the potentially very
surprising side-effect of having your local variable overwritten with a
different type.

The problem I'm describing is pretty serious for the one type-cast that
exists at present: __toString()

Example:

class Foo { public function __toString() { return "foo"; } }
function append_to(string &$str) { $str .= "_bar"; }
$foo = new Foo();
append_to($foo);
var_dump($foo); // string(7) "foo_bar"

In this example, the caller's instance of Foo gets wiped out and replaced
by a string - the "ping pong type-casting" that saved us in the previous
example won't save us this time.

While the side-effects for scalars being replaced by scalars may be "okay"
under most circumstances, I think this kind of side-effect is pretty
unnatural and surprising for any non-scalar type.

Most of the time, arguments are not by-reference, so I think changing this
this will likely have a pretty minimal impact on real world code - and the
work around (as in the previous example) is pretty easy to implement, and
could likely be fully automated by e.g. PHP Storm, CodeSniffer's cbf tool,
etc.

With this change, what Anthony proposed in 2012 becomes feasible, I think?

(And perhaps it comes feasible to (later) think about completing the
type-casting feature with support for casting between class/interface
types, but that's another subject...)


Re: [PHP-DEV] Directory separators on Windows

2017-04-01 Thread Rasmus Schultz
10 thumbs up ;-)

But this really demonstrates how badly we need this function - I bet any
number of those points may or may not be covered by any number of
implementations in the wild.

It would be so nice to have this done "right", once and for all.


On Sat, Apr 1, 2017 at 2:42 PM, Fleshgrinder  wrote:

> On 4/1/2017 2:01 PM, Anatol Belski wrote:
> > 1. optionally - yes, otherwise it should do platform default
> > 2. no, this kind of operation is a pure parsing, no I/O related checks
> needed
> > 3. irrelevant, but can be defined
> >
> > Other points yet I'd care about
> > - result should be correct for target platform disregarding actual
> platform, fe target Linux path Windows, or Windows path on Mac, etc.
> > - validation, particularly for reserved words and chars, also other
> platform aspects
> > - encodings have to be respected, or UTF-8 only, to define
> > - probably should be compatible with PHP stream wrapper namespaces
> >
> >
> > Thanks
> >
> > Anatol
> >
>
> 1. How do you envision that? If the path is `/a/b/../c` where only `/a`
> exists right now? It's unresolvable, assuming that `../` points to `/a`
> is wrong if `b/` is a symbolic link that points to `/x/y`.
>
> 2. Here I agree, casing cannot be decided without hitting the
> filesystem. Some are case-sensitive, some insensitive, and others
> configurable.
>
> 3. Does not matter for Windows itself, it is case-insensitive.
>
> (I continue the numbering for the points you raised.)
>
> 4. How would we go about normalizing a Windows path to POSIX? `C:\a` is
> not necessarily the same as `/a`, or should it produce `C:/a`?
>
> 5. 
>
> 6. I vote for UTF-8 only. We already have locale dependent filesystem
> functions, which also makes them kind of weird to use, especially in
> libraries. Another very important aspect to take care of this point is
> normalization forms. Filesystems generally store stuff as is, that means
> that we can create to files with the same name, at least by the looks of
> it, which are actually different ones. Think of `Ă€` which can also be
> `ä`. It is generally most advisable to stick to NFC, because that is
> also how users usually produce those chars.
>
> 7.  just forward I'd say.
>
> 8. Collapse multiple separators (e.g. `a//b` ~> `a/b`).
>
> 9. Resolve self-references, unless they are leading (e.g. `a/./b` ~>
> `a/b` but `./a/b` stays `./a/b`).
>
> 10. Trim separators from the end (e.g. `a/` ~> `a`).
>
> --
> Richard "Fleshgrinder" Fussenegger
>


Re: [PHP-DEV] Directory separators on Windows

2017-04-01 Thread Rasmus Schultz
> Also ucfirst is useless (or any case operations)

It's not useless, if you want a normalized path on Windows, it has to
include a drive-letter, and Windows FS isn't case-sensitive.

> Right now realpath will fail if the path does not exist

I know, that's one reason I don't use it.

It kind of solves a different problem, e.g. resolves ".." and "." elements
in paths... as a rule, I don't ever use relative paths, but it would
certainly be nice to have a realpath() that works for files that haven't
been created yet.

I don't think you can simply make realpath() also normalize the path, as
this would be a breaking change?

I guess an improved realpath() could be used internally as part of a
normalize_path() function, but it's not enough on it's own, since the real
path will still have platform-specific directory-separators, so a
normalize_path() function would still be useful if realpath() gets improved.

So to summarize, a normalize_path() function should:

1. Fully normalize to an absolute path with no platform-specific separators
2. Have corrected case (for files/dirs that do exist.)
3. Have normalized (upper-case) drive-letter on Windows

There's also network file-system paths on Windows with a different syntax
to consider? I don't know much about that...


On Fri, Mar 31, 2017 at 11:40 AM, Pierre Joye <pierre@gmail.com> wrote:

> On Fri, Mar 31, 2017 at 3:32 PM, Rasmus Schultz <ras...@mindplay.dk>
> wrote:
> > Well, this is the opposite of what I'm asking for, and does not address
> the
> > case where paths have been persisted in a file or database and the data
> > gets accessed from different OS.
> >
> > I understand the reasons given for not changing this behavior in PHP
> > itself, so maybe we could have a standard function that normalizes paths
> to
> > forward slashes? e.g. basically:
> >
> > /**
> >  * Normalize a filesystem path.
> >  *
> >  * On windows systems, replaces backslashes with forward slashes
> >  * and ensures drive-letter in upper-case.
> >  *
> >  * @param string $path
> >  *
> >  * @return string normalized path
> >  */
> > function normalize_path( $path ) {
> > $path = str_replace('\\', '/', $path);
> >
> > return $path{1} === ':'
> > ? ucfirst($path)
> > : $path;
> > }
>
> Also ucfirst is useless (or any case operations). realpath goes
> further down by solving ugly things like  \\\ or // (code
> concatenating paths without checking trailing /\.
>
> > At least WordPress, Drupal and probably most major CMS and frameworks
> have
> > this function or something equivalent. .
>
> Now I remember why they have to do that.
>
> realpath is not fully exposed in userland. virtual_file_ex should be
> used and provide the option to validate path or not. Right now
> realpath will fail if the path does not exist. I would suggest to
> expose this functionality/option and that will solve the need to
> implement such things in userland.
>
> ps: I discussed that long time with Dmitry and forgot to implement it,
> I take the blame for not having that in 7.x :)
>
> Cheers,
> Pierre
>


Re: [PHP-DEV] Directory separators on Windows

2017-03-31 Thread Rasmus Schultz
Well, this is the opposite of what I'm asking for, and does not address the
case where paths have been persisted in a file or database and the data
gets accessed from different OS.

I understand the reasons given for not changing this behavior in PHP
itself, so maybe we could have a standard function that normalizes paths to
forward slashes? e.g. basically:

/**
 * Normalize a filesystem path.
 *
 * On windows systems, replaces backslashes with forward slashes
 * and ensures drive-letter in upper-case.
 *
 * @param string $path
 *
 * @return string normalized path
 */
function normalize_path( $path ) {
$path = str_replace('\\', '/', $path);

return $path{1} === ':'
? ucfirst($path)
: $path;
}

At least WordPress, Drupal and probably most major CMS and frameworks have
this function or something equivalent.

This function is too trivial to ship as a separate package, but at the same
time, it's too error-prone and repetitive for every framework/project to
implement (and test) for itself... In my opinion, it's common enough that
it ought to just be built-in?


On Thu, Mar 30, 2017 at 5:45 PM, Kris Craig <kris.cr...@gmail.com> wrote:

>
> On Mar 30, 2017 8:21 AM, "Sara Golemon" <poll...@php.net> wrote:
> >
> > My first thought is UNC paths.  On windows a file server share is
> > denoted by \\host\share . if you combine that with relative paths
> > produced from PHP, you end up in the dubious situation of
> > "\\host\share/path/to/file" <--- wat?
> >
> > Overall, it smells of magic.
> >
> > -Sara
> >
> > On Thu, Mar 30, 2017 at 8:25 AM, Rasmus Schultz <ras...@mindplay.dk>
> wrote:
> > > Today, I ran into a very hard-to-debug problem, in which paths (to SQL
> > > files, in a database migration script) were kept in a map, persisted
> to a
> > > JSON file, and this file was moved from a Windows to a Linux
> file-system -
> > > because the paths on the Linux system had forward slashes, the files
> > > appeared to be missing from the map.
> > >
> > > Related questions are very commonly asked by Windows users, indicating
> that
> > > this is a common problem:
> > >
> > > http://stackoverflow.com/questions/14743548/php-on-
> windows-path-comes-up-with-backward-slash
> > > http://stackoverflow.com/questions/5642785/php-a-good-
> way-to-universalize-paths-across-oss-slash-directions
> > > http://stackoverflow.com/questions/6510468/is-there-a-
> way-to-force-php-on-windows-to-provide-paths-with-forward-slashes
> > >
> > > The answers that are usually given (use DIRECTORY_SEPARATOR, use
> > > str_replace() etc.) is that by default you automatically get
> cross-platform
> > > inconsistencies, and the workarounds end up complicating code
> everywhere,
> > > and sometimes lead to other (sometimes worse) portability problems.
> > >
> > > The problem is worsened by functions like glob() and the SPL
> directory/file
> > > traversal objects also producing inconsistent results.
> > >
> > > Returning backslashes on Windows seems rather unnecessary in the first
> > > place, since forward slashes work just fine?
> > >
> > > Might I suggest changing this behavior, such that file-system paths are
> > > consistently returned with a forward slash?
> > >
> > > Though this is more likely to fix rather than create issues, this
> could be
> > > a breaking change in some cases, so there should probably be an INI
> setting
> > > that enables the old behavior.
> > >
> > > Thoughts?
> >
> > --
> > PHP Internals - PHP Runtime Development Mailing List
> > To unsubscribe, visit: http://www.php.net/unsub.php
> >
>
> Another option would be to create a function that converts all slashes in
> a given input string to whatever the directory seperator should be on that
> platform.  This way, devs wouldn't have to deal with bulky aliases like
> DIRECTORY_SEPERATOR cluttering up their code.
>
> For example:
>
> 
> print convert_seperators( '/some\directory/' );
>
> ?>
>
> The above would output "/some/directory" on Linux and "\some\directory" on
> Windows.
>
> --Kris
>


[PHP-DEV] Directory separators on Windows

2017-03-30 Thread Rasmus Schultz
Today, I ran into a very hard-to-debug problem, in which paths (to SQL
files, in a database migration script) were kept in a map, persisted to a
JSON file, and this file was moved from a Windows to a Linux file-system -
because the paths on the Linux system had forward slashes, the files
appeared to be missing from the map.

Related questions are very commonly asked by Windows users, indicating that
this is a common problem:

http://stackoverflow.com/questions/14743548/php-on-windows-path-comes-up-with-backward-slash
http://stackoverflow.com/questions/5642785/php-a-good-way-to-universalize-paths-across-oss-slash-directions
http://stackoverflow.com/questions/6510468/is-there-a-way-to-force-php-on-windows-to-provide-paths-with-forward-slashes

The answers that are usually given (use DIRECTORY_SEPARATOR, use
str_replace() etc.) is that by default you automatically get cross-platform
inconsistencies, and the workarounds end up complicating code everywhere,
and sometimes lead to other (sometimes worse) portability problems.

The problem is worsened by functions like glob() and the SPL directory/file
traversal objects also producing inconsistent results.

Returning backslashes on Windows seems rather unnecessary in the first
place, since forward slashes work just fine?

Might I suggest changing this behavior, such that file-system paths are
consistently returned with a forward slash?

Though this is more likely to fix rather than create issues, this could be
a breaking change in some cases, so there should probably be an INI setting
that enables the old behavior.

Thoughts?


Re: [PHP-DEV] PCRE caching

2017-03-05 Thread Rasmus Schultz
Thanks for clearing this up, Nikita :-)

> Compiled expressions are cached between requests. However, they are not
shared between processes

That sounds good - it would likely very difficult (if not impossible) and
likely would make only a marginal performance difference. All good, I think.

> The cache invalidation strategy is FIFO

Okay, so, do cache entries move "to the front of the line" when there's a
cache hit?

I'm thinking, otherwise, a large number of dynamic expressions (which
don't, or only minimally, benefit from caching) might actually push static
expressions (which do benefit) out of the cache.

Just wondering. If invalidation of static expressions does happen in that
case, it likely doesn't impact most apps - I don't think dynamic
expressions are very common in most apps, though I have used it
occasionally for things like dictionary search...


On Fri, Mar 3, 2017 at 10:28 PM, Nikita Popov <nikita@gmail.com> wrote:

> On Wed, Mar 1, 2017 at 4:35 PM, Rasmus Schultz <ras...@mindplay.dk> wrote:
>
>> Hey internals,
>>
>> I was wondering whether or how PCRE regular expression get parsed and
>> cached, and I found this answer on Stack Overflow:
>>
>> http://stackoverflow.com/questions/209906/compile-regex-in-php
>>
>> Do I understand this correctly, that:
>>
>> 1. All regular expressions are hashed and the compiled expression is
>> cached
>> internally between calls.
>>
>
> Correct.
>
> 2. The /S modifier applies more optimizations during compile, but caching
>> works the same way.
>>
>
> Yes. Additionally, if PCRE JIT is enabled (which it usually is on PHP 7)
> we always study, independently of whether /S was specified.
>
>
>> 3. Compiled expressions are not cached between requests.
>>
>
> Compiled expressions are cached between requests. However, they are not
> shared between processes (I'm not even sure if that's possible.)
>
> The cache invalidation strategy is FIFO. More specifically, whenever the
> cache fills up, we discard the first 1/8 cached regular expressions.
>
> Nikita
>
>
>> If so, this seems far from optimal.
>>
>> Every unique regular expression needs to be compiled during every request,
>> right?
>>
>> So with FPM, or with long-running apps, we're missing an opportunity to
>> optimize by caching between requests.
>>
>> And with long-running apps, we're caching every dynamic regular
>> expression,
>> which could harm (memory overhead) more than help.
>>
>> Ideally, shouldn't we have (like some engines/languages) a switch to
>> enable
>> caching?
>>
>> The run-time can't know if a given regular expression is dynamic or
>> static,
>> can it? It's just a string either way - so without a switch, you're either
>> committing compiled dynamic expressions to the cache unnecessarily, and/or
>> missing an opportunity to cache between requests in long-running apps or
>> under FPM.
>>
>> I think most apps use quite a lot of regular expression for validation
>> etc.
>> so maybe there's a missed optimization opportunity here?
>>
>> Cheers,
>>   Rasmus Schultz
>>
>
>


Re: [PHP-DEV] New constants in DateTime

2017-03-02 Thread Rasmus Schultz
FWIW, these constants are not universal.

In Postgres (and MySQL since 5.7) the date+time types have optional
sub-second precision - which the "Y-m-d H:i:s" pattern will fail to parse.

Another common case in Postgres is date+time with timezone, e.g. used for
scheduling/calendar applications etc. - yet another pattern.

Not an argument against having these constants, at all, but they've already
been defined everywhere in userland where needed, so, as others have said,
I'm not really sure what adding them to the core will accomplish. We'll
likely still need other similar constants for other formats.

> It's surely easy to implement them in userland but that would require
> either global constants or a class in userland specifically for that
> purpose

I think it's more common to declare them in the class that needs them - for
such a small dependency as a date/time pattern, I would honestly prefer to
have them plainly visible, declared in the relevant class, next to other
related constants, such as date/time regex for input-validation, etc.

Likewise, I'd prefer to have minute/hour/day constants defined where needed
- I find that const DAY = 24*60*60 is more easily parsed and understood
than a predefined const DAY = 86400.

That's all based on personal preference - but namely because it is largely
a matter of convenience/preference/opinion, and since it's no burden to
declare these at all, perhaps these are good reasons to leave it in
userland.


On Thu, Mar 2, 2017 at 4:46 PM, Crocodile  wrote:

> While I agree with everything you're saying, I also think it could still be
> worth it to have those constants in core for the following reasons:
>
> 1. MINUTE, HOUR and DAY are particularly often used, 99.999% of the time in
> a context where it does not matter if a minute has 60 seconds or not, or if
> a day has 24h or not. Particularly often used to specify cache lifetime,
> for example.
> 2. It's surely easy to implement them in userland but that would require
> either global constants or a class in userland specifically for that
> purpose. Both ways are easy, but these constants I see in virtually any
> project, so for me it would be handy to have them in DateTime.
>
> But of course, I don't see it as a must-have, just as nice-to-have.
>
> Cheers,
> Victor
>
> On Thu, Mar 2, 2017 at 4:03 PM Andreas Heigl  wrote:
>
> > Hi Victor.
> >
> >
> > Am 02.03.17 um 15:48 schrieb Crocodile:
> > > Hello internals,
> > >
> > > A similar question should have been asked already but I haven't found
> > > anything so far when googling: I think DateTime class should have the
> > > following constants in addition to those already existing:
> > >
> > > const SQL = "Y-m-d H:i:s";
> > > const SQL_DATE = "Y-m-d";
> > > const SQL_TIME = "H:i:s";
> > > const SECOND = 1;
> > > const MINUTE = 60;
> > Not every minute has 60 seconds.
> > > const HOUR = 3600;
> > See above!
> > > const DAY = 86400;
> > Not every day has 86400 seconds. For one see the comment on MINUTE and
> > also there are days that have more or less than 24 hours (DST)
> >
> > Therefore I wouldn't want to see those constants (that are also very
> > easy to put up in userland - even though they aren't correct) in the
> > PHP-Core.
> >
> > And as the SQL-Constants are also easily to implement in userland I'm
> > not sure it makes to add them to the core

> >
> > But that's just my 0.02€
> >
> > Cheers
> >
> > Andreas
> >
> >
> > --
> >   ,,,
> >  (o o)
> > +-ooO-(_)-Ooo-+
> > | Andreas Heigl   |
> > | mailto:andr...@heigl.org  N 50°22'59.5" E 08°23'58" |
> > | http://andreas.heigl.org   http://hei.gl/wiFKy7 |
> > +-+
> > | http://hei.gl/root-ca   |
> > +-+
> >
> > --
> Best regards,
> Victor Bolshov
>


[PHP-DEV] PCRE caching

2017-03-01 Thread Rasmus Schultz
Hey internals,

I was wondering whether or how PCRE regular expression get parsed and
cached, and I found this answer on Stack Overflow:

http://stackoverflow.com/questions/209906/compile-regex-in-php

Do I understand this correctly, that:

1. All regular expressions are hashed and the compiled expression is cached
internally between calls.

2. The /S modifier applies more optimizations during compile, but caching
works the same way.

3. Compiled expressions are not cached between requests.

If so, this seems far from optimal.

Every unique regular expression needs to be compiled during every request,
right?

So with FPM, or with long-running apps, we're missing an opportunity to
optimize by caching between requests.

And with long-running apps, we're caching every dynamic regular expression,
which could harm (memory overhead) more than help.

Ideally, shouldn't we have (like some engines/languages) a switch to enable
caching?

The run-time can't know if a given regular expression is dynamic or static,
can it? It's just a string either way - so without a switch, you're either
committing compiled dynamic expressions to the cache unnecessarily, and/or
missing an opportunity to cache between requests in long-running apps or
under FPM.

I think most apps use quite a lot of regular expression for validation etc.
so maybe there's a missed optimization opportunity here?

Cheers,
  Rasmus Schultz


Re: [PHP-DEV] [RFC][DISCUSSION] Object type hint, now with added variance

2017-02-15 Thread Rasmus Schultz
In the light of this, maybe enums (assuming this feature comes first)
should be implemented as immutable objects rather than values?

Type-checking for enums would be important, so in PHP terms, an enum
"instance" would likely be closer to an object than a value in nature
anyway.

The way I look at it, this feature doesn't prevent enums from happening, it
just changes the design parameters.

Just a thought.


On Wed, Feb 15, 2017 at 4:34 PM, Andrea Faulds  wrote:

> Hi Marco,
>
> Marco Pivetta wrote:
>
>>
>> Since the engine is clueless about types until autoloading happens, this
>> is
>> easily solvable by providing a marker syntax for non-object hints. For
>> instance `function foo() : enym:MyEnum {}`
>>
>
> If we're going to do prefixes for non-classes, we might as well copy C
> outright: `enum MyEnum`.
>
> Thanks.
> --
> Andrea Faulds
> https://ajf.me/
>
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] Namespaces in Core

2017-02-07 Thread Rasmus Schultz
Just my two cents, but moving and aliasing core PHP
classes/interfaces/functions sounds like an absolutely horrible idea.

My biggest question is WHY would you do that?

Writing user-space code today that uses the global namespace would be
considered extremely bad practice - no one should do that.

If you move everything from the root namespace into new namespaces, what
will that accomplish? You'll have an empty root namespace. But for what?

If nobody else is using the root namespace for anything, how is it
problematic for the language itself to do that?

Besides, it'll be a decade before you can actually remove the root
namespace aliases.

I don't see the point of changing this, at all.

It will lead to inconsistent code and a lot of meaningless overhead for
developers - who, ultimately, stand to gain nothing from this change.


On Mon, Feb 6, 2017 at 9:27 PM, Sara Golemon  wrote:

> On Mon, Feb 6, 2017 at 12:21 PM, Fleshgrinder 
> wrote:
> > First: I like namespaces in Core but here me out!
> >
> > The PHP (case does not matter) would be the proper vendor name to put
> > Core stuff in, as far as I remember it is also reserved for PHP
> > functionality. There were also numerous discussions about providing a
> > cleaned up API there while maintaining backwards compatibility via
> > aliases and so forth in the non-namespaced Core stuff.
> >
> I've been having this same thought lately since looking at the sodium
> RFC.  Here are my thoughts, centered on the goal of having classes
> (and maybe functions?) in a \php\{extname}\ namespace hierarchy.
>
> New classes within 7.2 (e.g. \HashContext) to be moved without concern
> for BC (e.g. \php\Hash\HashContext)
>
> Older classes (e.g. \RecursiveIteratorIterator) to be moved AND
> ALIASED FOR BC (e.g. \php\SPL\Iterator\RecursiveIteratorIterator)
>
> "Aliasing" could be potentially accomplished in a few ways:
> 1. Literally just class_alias().  Put another copy of the
> zend_class_entry into the EG(class_table) under a different name.
> 2. "Auto-use": Compile-time analysis of classname: "Is it in this list
> of BC classes? Implicitly map it."
> 3. ...?
>
> I like #2 because we can raise compile-time deprecation warnings and
> we don't introduce any runtime overhead for most cases.
>
> Obviously, no removal of support for non-namespaced names until AT LEAST
> PHP 8.0
>
> This two big unanswered questions for me before I'd put this into an RFC
> are:
> 1. How to achieve BC in the best way
> 2. What to do about functions/constants? Instinct says move 'em just
> like classes.
>
> -Sara
>
> P.S. - wrt libsodium, I think THIS issue is enough for me to come down
> on the side of voting non-namespaced to avoid it being an odd-duck.
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] [RFC][Discuss] Arrow Functions

2017-02-05 Thread Rasmus Schultz
I'd strongly prefer a syntax without the introduction of "fn" keyword -
e.g. similar to closures in other languages.

I also feel that there's a feature missing - something that was possible
with closures:

$total = 0;

$add = function ($value) use (&$total) {
$total += $value;
};

Per the RFC:

> When a variable in the expression is defined in the parent scope it will
be captured implicitly by-value

Whether you regard it as a good thing or bad thing (I'm only pointing it
out) this is inconsistent with JavaScript, where variables in the parent
scope are captured by-reference.

If we're introducing a new form and syntax for closures, why not make this
one align with something that's going to be familiar with developers?

That's just my opinion, but whether you agree with that or not - as long as
we're introducing a new form and syntax, why make it *less* capable than
ordinary PHP closures? At the very least, I feel there should be feature
parity - otherwise, code in the wild is going to continue to be a strange
mess of one form or the other, which doesn't help with language
comprehension at all, especially when both forms also work differently from
JavaScript closures, which are likely the form of closures that
web-developers are going to be most familiar with.

Don't get me wrong, I'm not saying "make it like JavaScript" - what I'm
saying is, make something that is familiar to developers *somehow*, e.g.
either provide feature parity with ordinary PHP closures and make it
familiar to PHP developers, *or* make it similar to JavaScript closures,
but don't throw yet another "original" idea on the pile.

Ultimately, I think what I'd like to see would be something along the lines
of this:

$total = 0;

$add = ($value) => {
&$total += $value;
};

That is:

- Lose the fn keyword - get the syntax down to something similar to
closures in most other languages.
- Keep it working like PHP (which you intend to do anyhow) in terms of
importing variables by-value.
- Provide feature parity with regular PHP closures by providing some means
of accessing variables by-reference.

I understand that the fn keyword is there to remove ambiguities, but I
think working around the ambiguities is possible, even if it's difficult -
there was ambiguity with < and > operators in the run-of-the-mill generics
syntax I proposed last year, and Dominic Grostate was able to work through
them and get it to parse after all. I understand it's probably difficult,
and it may not be possible to achieve something that is 100% technically
correct, but it's usually possible to achieve something that works for
almost any real-world use-case.

The last thing I would comment on is multi-statement bodies. Omitting this
is, in my opinion, a very bad decision - it will, again, lead to lack of
feature parity with regular closures, which will mean, in practice,
factoring back and forth between regular closures and fat arrow functions,
which will be frustrating. It will also encourage developers to attempt to
fold complex operations into a single expression, leading to further
frustration for the programmer, and unreadable code for collaborators,
because "damnit I'm not going back to regular closures!", right?

In my opinion, if you can't provide feature parity on these points with
regular closures, this feature will hurt more than help - it will lead to a
lot of meaningless struggles, unreadable code, and code that doesn't
refactor well, and, eventually, BC breaks when PHP 7.x finally does
introduce these missing features.


On Mon, Jan 30, 2017 at 6:55 PM, Levi Morrison  wrote:

> Bob Weinand and I are happy to announce that the [Arrow Functions][1]
> RFC is moving into the public discussion phase. We have been
> collaborating on this RFC for many months now and finally have a
> proposal we are happy to discuss in the open.
>
> Here is an example of an existing closure:
>
> function ($x) use ($arr) {
> return $arr[$x];
> }
>
> This RFC proposes syntax and semantics to simplify this common usage to:
>
> fn($x) => $arr[$x]
>
> More details are in the RFC. The [implementation][2] currently has no
> known issues and is ready for you to download, build and test, which
> we encourage you to do.
>
> We look forward to a productive discussion period and are happy to
> answer questions.
>
> For historical purposes, the revision of this RFC is currently at
> [1485798604][3].
>
>   [1]: https://wiki.php.net/rfc/arrow_functions
>   [2]: https://github.com/morrisonlevi/php-src/tree/arrow_functions
>   [3]: https://wiki.php.net/rfc/arrow_functions?rev=1485798604
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] PHP's support to contravariance and covariance

2017-01-31 Thread Rasmus Schultz
We were talking about this exact issue at work today.

Supporting this for interfaces would be particularly useful - if an
implementation better than satisfies the requirements defined by an
interface, it should be able to implement that interface.

I'd be very happy to see an RFC for this :-)


On Tue, Jan 31, 2017 at 7:30 PM, guilhermebla...@gmail.com <
guilhermebla...@gmail.com> wrote:

> Hi internals,
>
> During my regular open source work, I realized that PHP yet do not support
> contravariance and covariance for user classes.
>
> Some examples that I found that could be really easy to implement and
> useful to end user are highlighted here:
>
> - contravariance.php - https://3v4l.org/I3v0u
> - covariance.php - https://3v4l.org/i79O5
>
> For all those lazy people that don't want to open 2 new tabs to understand
> what I mean, here's a more elaborate example covering both scenarios:
>
> 
> class A {}
>
> class B extends A {}
>
> class Foo {
> public function bar(B $b) : A {}
> }
>
> class Woo extends Foo {
> public function bar(A $b) : B {}
> }
>
> $w = new Woo();
>
> Basically, here are the highlights:
> - method arguments are ok to reference wider parameter types (and we just
> approved the PR for Parameter Type Widening) - this is what we call
> contravariant, as contra inheritance direction
> - return types are ok to enforce strictness for subtypes - this is what we
> call covariant, as Woo is a subtype of Foo
>
> I've walked through PHP source and it looks like the only needed place to
> modify is
> https://github.com/php/php-src/blob/master/Zend/zend_inheritance.c#L184,
> which would require to be decoupled in 2 functions to check which direction
> is should support (covariance or contravariance).
>
> Is there anything else that I am missing? I'm happy to write an RFC for
> that... =)
>
> Cheers,
>
> --
> Guilherme Blanco
> Senior Technical Architect at Huge Inc.
>


Re: [PHP-DEV] Fwd: Type Collection

2017-01-30 Thread Rasmus Schultz
> Basically Foo[] to indicate an array of objects of type Foo

I would be fine with that, as long as it's sugar for array


On Sun, Jan 29, 2017 at 4:51 PM, Sebastian Bergmann 
wrote:

> Am 28.01.2017 um 17:10 schrieb Niklas Keller:
> > sounds like everything you want is typed arrays?
>
> I would love typed arrays. Basically Foo[] to indicate an array of objects
> of type Foo. IDEs such as PhpStorm as well as documentation tools already
> support this syntax when used in docblocks.
>
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] Fwd: Type Collection

2017-01-29 Thread Rasmus Schultz
> The Collection is Iterable, Traversable, Countable like an array to be
> compatible with foreach and other Traversable-compatibles functions.

Right, so it's an array.

Except, it's an object-type, rather than a value-type like arrays. (I'm
guessing - I don't think you specified?)

And it's type-checked.

So what you're really describing is generic arrays:

https://wiki.php.net/rfc/generic-arrays

I would strongly prefer we don't venture into generics for isolated cases
like collections.

I would also strongly prefer a generic collection-type that is a
value-type, rather than an object. (which may or may not be what you're
proposing?)

I would also strongly prefer an approach that builds on the foundation of
arrays, rather than tries to replace them - introducing yet another
collection-type creates even more disparity in the language, e.g. yet
another collection-like thing that's passed by reference and begets
side-effects, surprising behavior, and bugs.

Introducing generic features like this one in small increments, in my
opinion, is harmful in the long term - it would be much better to introduce
generics consistently, across the board, as a language feature, rather than
as a use-case-specific feature.

This is my general opinion about languages. Go, for example, has 3 or 4
use-case-specific generic features, but doesn't have generics as a language
feature, and it's horrible - it puts you in the mode of programming with
generics for those use-cases, and then having to come up with complex
architectural work-arounds when you venture outside the confines of the 3-4
use-cases the design team thought were important.

This sort of thing begets inconsistency, and PHP has too many as it is.

Just my two cents.


On Sat, Jan 28, 2017 at 4:37 PM, georges  wrote:

> Hello
> ​ ​
> Php Internals,
>
> I was wondering today why did we not have (yet ?)​
> ​ ​
> a Collection type in Php ?
> Typically what would be that kind of variable type ?
>
> This type would be a great intermediate between an array and an Object.
> Today, in my opinion we are seeing to much wrong uses of php Object.
> To quote one of the most used: The Doctrine Collection object.
> These kind of object are IMO very memory-greedy ones.
>
> The implementation idea would be to have a new variable type:
> The Collection.
> The Collection is Iterable, Traversable, Countable like an array to be
> compatible with foreach and other Traversable-compatibles functions.
> The Collection become a type on it's
> ​ ​
> own, so there's a lot of changes to be considered:
> - The serialization
> - The vardumping/exporting
> - The Exception traces
> - The backtrace
>
> To be syntaxely compliant to array and object it would be case insensitive
> even if i would like to prefer it Camelcased: Collection. This is up to
> you.
> The target is Php 8, but the reserved word could be introduced in php 7.3.
>
> Here's are very basics implementation concepts:
>
> /**
>  * Standard var declaration
>  */
> $collection = Collection(int);
>
> /**
>  * Alternative var declaration
>  */
> $collection = Collection(int, [1, 2, 3]);
>
> // Throws nothing
> $collection[]= 10;
> $collection['abc']= 10;
>
> // Throws CollectionTypeHintError
> $collection = Collection(int, [1, '2', 3]);
> $collection['abc']= '10';
> $collection['abc']= new StdClass;
>
> // Transtypes the collection to an standard array
> $collectionAry = (array) $collection;
>
> // Throws CollectionTypeReHintingError
> $collection = (array) $collection;
> $collection = 10;
>
> // Throws nothing
> unset($collection);
> $collection = 10;
>
>
> Now the +/-;
>
> The +:
> + We have an optimized Collection type instead of those ugly Object-like
> collections that are ressources-greedy.
> + Aside of the optimization, we have a well understandable type hint
> reserved to the Collections. This is clearly a better
> semantically-appropriated way to work with Collection data.
>
>
> The -:
> - Collection become a reserved word. Therefore, this could introduce a
> major BC.
>
>
> Cheers,
> Georges.L
>


Re: [PHP-DEV] Not autoloading functions

2017-01-28 Thread Rasmus Schultz
> old applications could maintain compatibility only
> by adding a simple autoloader that would alias the global
function/constant
> into the calling namespace

So as a side-effect of calling any function, my namespace would get
polluted with all sorts of random names? That sounds like a messy
work-around.

Okay, so take it back for a moment.

The problem case is this, right?

namespace Foo;
bar();

If the function Foo\bar() has not already been loaded, we fall back to
bar() in the global namespace.

With a function-autoloader in place, we would need to trigger this for
every function-call from any namespace, and that's unacceptable.

Okay, well, existing code does not expect function autoloading and wouldn't
benefit from it without changes, right?

So what if, instead of trying to autoload everything by default, we make it
opt-in? Something like:

namespace Foo;
use namespace Foo;
bar();

Now, if function Foo\bar() has not been defined yet, and function \bar()
doesn't exist, then start trying trying to autoload them from used
namespaces.

Okay, that may seem a bit redundant - having to explicitly indicate I'd
like to be able to call functions from within the file's own namespace.

But it'll make more sense if you put your functions in a functions-only
namespace:

namespace Foo;
use namespace Foo\Functions;
bar();

This call would prefer Foo\Functions\bar() if it is able to autoload that,
otherwise will try \bar().

Or if you have several function-namespaces:

namespace Foo;
use namespace Click, Clack;
bar();

This would prefer Click\bar(), then Clack\bar(), if any of those can
autoload, otherwise will try \bar().

Now, this is still a lot of autoload queries, e.g. one for every function
called in every file.

It also doesn't address the issue of autoloading constants.

So.

What if we don't autoload functions at all?

What if we autoload namespaces instead?

That reduces the number of autoload queries from one per function to one
per namespace, which might be more acceptable??

It does mean that individual functions and constants cannot be autoloaded -
the smallest unit that can autoload will be a namespace.

I think that's an okay limitation?

For the most part, packages will likely want to ship a set of functions
(and/or constants) as a single file anyway. If a vendor has too many
functions and don't want the overhead of loading them as a single file,
they likely can/should be organized into several (sub) namespaces anyhow,
so maybe that's acceptable.

So by default, there would be no namespace-autoloading for the file's own
namespace - we don't query the namespace-autoloader by default.

As for use function:

namespace Foo;
use function Blip\bar();
bar();

This would trigger namespace auto-loading for Blip when bar() is invoked.

So existing code with function imports could switch to
namespace-autoloading.

Code that currently uses include/require to load functions into a
file-namespace will need to remove their include/require statements, so
needs changes anyhow to use namespace-autoloading - if this code also needs
an added "use namespace" statement to achieve namespace-autoloading, that's
probably okay?

So yeah, this form of autoloading is a bit inconsistent with the name
resolution rules - but it doesn't require any change as drastic as changing
the function name resolution rules, it's pretty simple, and (I think?)
backwards-compatible.

It could also potentially save you a lot of explicit "use function"
statements, since you can replace ranges of function-imports (from the same
namespace) with a single namespace-import. When new functions are added to
imported namespaces, they would be immediately callable, without needing to
add more imports first.

One drawback or risk of this approach, is of files importing multiple
namespaces, e.g.:

use Foo, Bar;
baz();

If you're currently calling Bar\baz() and then a function Foo\baz() is
introduced, unwittingly you would now be calling that.

That's a pretty marginal issue though - function name collisions probably
aren't very likely to happen, especially within the same file.

Thoughts?


On Fri, Jan 27, 2017 at 4:29 PM, Wes  wrote:

> Importing functions from a static class would equally require to have all
> functions in the same file. I was proposing an alternative to that, not
> "symbol to file" autoloading.
>
> Though, I know that problem well, sadly. I've suggested PHP should just
> deprecate the fallback to root namespace, and remove the feature altogether
> in PHP8.
>
> Imho it's the only way to actually solve this. Some say it would be a huge
> BC break, but in reality old applications could maintain compatibility only
> by adding a simple autoloader that would alias the global function/constant
> into the calling namespace. Roave wrote this
> https://github.com/Roave/FunctionFQNReplacer , PHPStorm is supporting the
> no-fallback referencing:
> 

Re: [PHP-DEV] Pipe Operator v2

2017-01-26 Thread Rasmus Schultz
Besides, I mean, I'm sure this has occurred to everyone, right?

https://gist.github.com/mindplay-dk/4ef61fd5c0a35e5aa8fc699febb86487

I personally find that this new syntax you're proposing requires a lot of
parsing.

I mean, whenever you see substr() or array_map() etc. you're intuitively
expecting the first argument to be the first argument, right? Now you have
to backtrack through other lines and figure out the context, or try to spot
the $$ and count arguments to figure out which is which.

Just using intermediary variables seems pretty straight-forward and
harmless, so that would be my personal preference - if my coworkers started
using this everywhere, I would likely refactor the code and introduce more
variables in the process of trying to parse and make sense of it.

IMO, shorter, isolated constructions are always easier to read, write,
understand and change than the much longer constructions with the new
operator shown in the RFC.

But I also stay away from fluent APIs for the same reason, so there's that.

Maybe it comes down to personal preference - it's definitely not to my
taste, sorry...


On Wed, Jan 25, 2017 at 7:06 AM, Stephen Reay <php-li...@koalephant.com>
wrote:

> As a userland developer I feel $$ (or some variation starting with $) is
> reasonably natural - it's a variation on a regular variable.
>
>
>
> Sent from my iPhone
>
> > On 25 Jan 2017, at 03:53, Levi Morrison <le...@php.net> wrote:
> >
> >> On Tue, Jan 24, 2017 at 12:25 PM, Rasmus Schultz <ras...@mindplay.dk>
> wrote:
> >> Isn't `_` more generally used as a "discard" placeholder in most
> languages?
> >>
> >> At least in Swift, Go, Scala, Dart and C# (starting with v7) I think?
> >>
> >> I don't recall having seen it mean "fill in the blank". In what
> languages?
> >>
> >>
> >>> On Fri, Jan 20, 2017 at 4:26 PM, Levi Morrison <le...@php.net> wrote:
> >>>
> >>> Oops, sorry for an email that just quotes others; mis-clicked send.
> >>>
> >>>> Last, a cosmetic suggestion : replace '$$' with '$<' (more explicit as
> >>>> 'input data', imo).
> >>>
> >>> If we aren't going to use `$$` I'd like to use `_` or `__` which read
> >>> similar to "fill in the blank" and has precedence in other languages.
> >>>
> >>> But at this stage I'd much rather focus on changing the general model
> >>> to what I've proposed instead of what is outlined in the RFC. I care
> >>> much more about the feature than the exact syntax for it.
> >>>
> >>> --
> >>> PHP Internals - PHP Runtime Development Mailing List
> >>> To unsubscribe, visit: http://www.php.net/unsub.php
> >
> > Scala does use it this way. It also uses it in pattern matching to
> > mean "match anything else" or "I don't care about this one".
> >
> > --
> > PHP Internals - PHP Runtime Development Mailing List
> > To unsubscribe, visit: http://www.php.net/unsub.php
> >
>
>


Re: [PHP-DEV] Re: Not autoloading functions

2017-01-26 Thread Rasmus Schultz
> if you choose to use static methods instead of functions

It's not a choice - functions are practically useless in a Composer
context, and most everything PHP is now Composer packages.

> why do you need this special syntax for calling them then?

Yeah, but the same logic applies to namespaces and classes:

If you choose to use namespaces, why do you need aliases for classes?

Strictly speaking, you don't - but it would be really ugly and
inconvenient. Forcing you to qualify a namespace or the parent class of a
function repeatedly is just noise, same as qualifying the namespace before
every class or interface-reference.

Agreed, it has no functional value, but neither does namespace-aliasing.

Both have a considerable organizational benefit though: the ability to list
all your class, interface and function imports at the top of a file.

To me, that's valuable.

Either way, guys, here's a preliminary RFC:

https://wiki.php.net/rfc/use-static-function

While trying to describe this, I have to say, this doesn't appear to be the
slam-dunk it seemed to be - you can read the details on that page, but
given the two alternative approaches described on this page, it seems this
feature is likely to create just as many problems and WTF as the
auto-loading RFC.

I'm afraid one isn't much better or worse than the other in that sense
really...

Oh well :-/


On Thu, Jan 26, 2017 at 6:50 PM, Niklas Keller  wrote:

> > The problem with stop-gap measures is they become entrenched, and the
>> proper solution doesn't get implemented
>>
>> This would be my general point of view - unfortunately, functions are
>> essentially useless at present, in a world with Composer, unless you're
>> willing to preload all functions from all packages up-front.
>>
>> The only suggested solutions I've heard for the name resolution issue with
>> function autoloading frankly are all horrible - much worse than this
>> simple
>> alternative.
>>
>> Add to that the fact that likely 90% of all functions in the wild (at
>> least
>> in Composer packages) are currently implemented as public static
>> functions,
>> and in my opinion, this is starting to sound less like a stop-gap and more
>> like a simple solution to a problem we've been solving with a stop-gap
>> for,
>> oh, 10 years or so...
>
>
> Again, if you choose to use static methods instead of functions, why do
> you need this special syntax for calling them then?
>
> Regards, Niklas
>


Re: [PHP-DEV] Re: Not autoloading functions

2017-01-26 Thread Rasmus Schultz
> The problem with stop-gap measures is they become entrenched, and the
proper solution doesn't get implemented

This would be my general point of view - unfortunately, functions are
essentially useless at present, in a world with Composer, unless you're
willing to preload all functions from all packages up-front.

The only suggested solutions I've heard for the name resolution issue with
function autoloading frankly are all horrible - much worse than this simple
alternative.

Add to that the fact that likely 90% of all functions in the wild (at least
in Composer packages) are currently implemented as public static functions,
and in my opinion, this is starting to sound less like a stop-gap and more
like a simple solution to a problem we've been solving with a stop-gap for,
oh, 10 years or so...


On Jan 26, 2017 10:05 AM, "Andrea Faulds" <a...@ajf.me> wrote:

> Hi,
>
> Rasmus Schultz wrote:
>
>> Since the autoloading functions proposal is stalled, how about allowing
>> for
>> import of static functions instead?
>>
>
> The problem with stop-gap measures is they become entrenched, and the
> proper solution doesn't get implemented. But we may be at the risk of the
> latter anyway.
>
> --
> Andrea Faulds
> https://ajf.me/
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] Pipe Operator v2

2017-01-24 Thread Rasmus Schultz
Isn't `_` more generally used as a "discard" placeholder in most languages?

At least in Swift, Go, Scala, Dart and C# (starting with v7) I think?

I don't recall having seen it mean "fill in the blank". In what languages?


On Fri, Jan 20, 2017 at 4:26 PM, Levi Morrison  wrote:

> Oops, sorry for an email that just quotes others; mis-clicked send.
>
> > Last, a cosmetic suggestion : replace '$$' with '$<' (more explicit as
> > 'input data', imo).
>
> If we aren't going to use `$$` I'd like to use `_` or `__` which read
> similar to "fill in the blank" and has precedence in other languages.
>
> But at this stage I'd much rather focus on changing the general model
> to what I've proposed instead of what is outlined in the RFC. I care
> much more about the feature than the exact syntax for it.
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] Not autoloading functions

2017-01-21 Thread Rasmus Schultz
> How hard is it to write Foo::bar? You never have to go more
than one level. I don't see a point in mixing internal function
namespace with class methods for the sake of saving typing couple of
characters.

I'm not suggesting we mix namespaces - this of course would be file-local,
same as use-statements in general.

You likely have to write a use-statement either way, if you're going to
call a static function, e.g.:

use Foo\Bar\HtmlHelper;
echo HtmlHelper::escape($text);

Versus:

use Foo\Bar\HtmlHelper::escape;
echo escape($text);

It's not about "saving characters", that's not what use-statements are for
- it's to avoid qualifying the same references repeatedly, which (for one)
is better for source-control, whether that's a namespace or a class-name
being repeated.

Anyhow, it sounds like most of you are positive about this idea, so I will
ponder the details and post a small RFC :-)


On Jan 20, 2017 19:55, "Stanislav Malyshev"  wrote:

Hi!

> Since the autoloading functions proposal is stalled, how about allowing
for
> import of static functions instead?
>
> use function Foo::bar;
>
> bar(); // calls Foo::bar()

I'm not sure why it is good. This would certainly be confusing, if you
call strlen and turns out it's completely different function from what
you thought. One thing when it's the same namespace, at least you can be
aware what this package does, but if it's just an arbitrary function
from anywhere, it's really bad for understanding the code.

How hard is it to write Foo::bar? You never have to go more
than one level. I don't see a point in mixing internal function
namespace with class methods for the sake of saving typing couple of
characters.

--
Stas Malyshev
smalys...@gmail.com


[PHP-DEV] Not autoloading functions

2017-01-19 Thread Rasmus Schultz
Just a quick thought.

Since the autoloading functions proposal is stalled, how about allowing for
import of static functions instead?

use function Foo::bar;

bar(); // calls Foo::bar()

There are two benefits to this approach:

1. There is immediate support for autoloading without any need for adoption
or support in existing autoloaders.

2. Pseudo-namespaces (abstract classes with stateless static functions) are
already widely practiced in PHP - a lot of existing code would be supported
as is.

The syntax when calling functions would be the same.

If we had function autoloading, we would likely collect related functions
in a file anyway - putting them in a class instead gives more less the same
exact result.

The only drawback I can see, is the inability to import a whole set of
functions with one statement - but being explicit about external imports is
widely considered best practice for classes and interfaces, so why not for
functions. Yeah, it's a bit inconvenient, but at least we can move ahead
and leverage existing code without changes or BC breaks. It's not all bad.
It's better than nothing perhaps? :-)

Thoughts?


Re: [PHP-DEV] Typed properties problems

2017-01-17 Thread Rasmus Schultz
On regular PHP 7, the array weirdness (Dmitry's last example) doesn't even
produce a warning:

class Shit {
public $yo = false;
}

$shit = new Shit();

$shit->yo[] = "what"; // quitly turns $yo into an array!

echo gettype($shit->yo); // array

That's pretty messed-up right there. At least in the object cases there's
an E_WARNING "Creating default object from empty value" - with the array
case, nothing, it just converts your boolean into an array. Yikes.


On Tue, Jan 17, 2017 at 11:03 AM, Dmitry Stogov  wrote:

> Hi Bob,
>
>
> I've found a number of problems:
>
>
> $ sapi/cli/php -r 'class Foo {public bool $b = false;} $x = new Foo;
> $x->b->ops += 5; echo gettype($x->b),"\n";'
>
> object
>
> $  sapi/cli/php -r 'class Foo {public bool $b = false;} $x = new Foo;
> $x->b->ops++; echo gettype($x->b),"\n";'
> object
>
> $  sapi/cli/php -r 'class Foo {public bool $b = false;} $x = new Foo;
> $x->b->ops = 5; echo gettype($x->b),"\n";'
> object
>
> $  sapi/cli/php -r 'class Foo {public bool $b = false;} $x = new Foo;
> $x->b[] = 5; echo gettype($x->b),"\n";'
> array
>
> Thanks. Dmitry.
>
>


Re: [PHP-DEV] [RFC] Parameter No Type Variance

2016-11-29 Thread Rasmus Schultz
But this leads to code that can't pass static inspections?

interface Joiner {
public function join(array $array): string;
}

class WideJoiner implements Joiner {
public function join($iterable): string {
$array = is_array($iterable) ? $array :
iterable_to_array($iterable);

return implode(", ", $array);
}
}

function joinWith(Joiner $joiner, $iterable) {
return $joiner->join($iterable); // <-- invalid argument ?
}

According to the Joiner abstraction, only array is accepted, and that's all
a static analysis tool can know about the $joiner argument in the
joinWith() function.

Being unable to pass static inspections is one thing, but this also makes
the code generally difficult to explain - there's a contract, Joiner, which
states that an array is required - to a person reading the joinWith()
function, that's all they can know about a Joiner instance; it isn't safe
for anybody to depend on a specific implementation of Joiner with a widened
argument-type, unless they read through the entire codebase and happen to
know about the WideJoiner implementation, but even then, someone using the
joinWith() function would also need to know which implementation of Joiner
is being passed, which seems to defeats the purpose of even having an
abstraction in the first place?


On Mon, Nov 21, 2016 at 10:39 AM, Niklas Keller  wrote:

> Morning Internals,
>
> I'd like to announce a RFC to allow omitting the type declarations for
> parameters in subclasses:
> https://wiki.php.net/rfc/parameter-no-type-variance
>
> PHP doesn't currently allow variance for parameters as checking these for
> compatibility isn't possible on compile time.
> This limitation is caused by autoloading and doesn't allow widening the
> accepted parameters.
>
> This RFC proposes to allow ommiting the type entirely in a subclass, as
> dropping all parameter constraints is
> always valid according to the LSP principle.
>
> We already allow return types being added in subclasses.
>
> Your feedback is welcome. :-)
>
> Regards, Niklas
>


Re: [PHP-DEV] Immutability RFC

2016-11-20 Thread Rasmus Schultz
Reading through the RFC and the replies, I'm confused about this question.

Why would the comparison operators work any differently on immutable
objects?

If these were value objects, the question would make sense, but it doesn't
sound like that's what you're proposing?

With regards to the feature itself, I frankly don't feel like it makes any
sense. I disagree with the entire premise of the RFC.

> Currently PHP lacks native support for immutability.

No, it doesn't. You show several examples of immutable classes in the RFC,
then demonstrate a slightly more abbreviated syntax to accomplish the same
thing.

> Because of that user-land applications are using third party libraries or
resort to custom implementations and still there is no easy enforcement of
immutability.

Really? There are third-party libraries for immutable classes?  Why?

It's true that there is no way for a class, internally, to enforce
immutability on itself - but why would you need to do that? You're writing
the class. If you want immutable state inside your class, simply don't
change the state.

Why would you need the language to enforce rules that you can already
enforce with the language?

> Introducing this feature would help bring one unified solution to this
problem, and also it would remove unnecessary logic from user-land
applications.

What is this unnecessary logic you're referring to? Get-methods generally
do not contain logic. There is no more or less logic in the examples you
show in your before/after code samples.

Perhaps you mean boilerplate? So yes, this feature removes a little bit of
boilerplate. Writing immutable classes becomes a little less ceremonious.

I think that the problem of writing get-methods is exaggerated and somewhat
contrived.

This feature doesn't enable you to do something you couldn't do before - it
obviates the need to write get-methods, but that's basically all, and I'm
not even convinced that's a good thing.

Public properties, in practice, are almost never used in PHP code. You very
rarely see anybody use them, because they're not generally safe, e.g.
permits client code to inject values of the wrong type, etc.

What you're proposing will make public properties the default for immutable
objects.

This will lead to inconsistencies - for example:

immutable class Name {
public $first;
public $last;
public function getFullName() {
return "{$this->first} {$this->last}";
}
}

This will get confusing quickly - you will have to learn or memorize which
attributes of your model are available as properties or methods, e.g.
$name->first is pretty far removed from $name->getFullName() both in terms
of syntax and style.

I think this will become quite confusing in practice, as nobody currently
expects or looks for public properties.

Also, having to refactor from a get-method to a public property, or
vice-versa, becomes a chore that causes a breaking change.

The term 'immutable", especially for the property-annotation, doesn't
strictly seem correct to me either, as for example, I can annotate a public
property as immutable, but if I put an object in there, that object is not
necessarily immutable. The correct term for this feature, especially for
properties, I would think is "readonly" - which would be consistent with
the description of certain existing properties in PHP APIs, such as
PDOStatement::$queryString, as well as with other languages such as C#.

Either way, this feature proposes to introduce "asynchronous" properties as
a new concept in PHP, where properties are generally "synchronous", in the
sense that they can always be read and written. Other languages that
support asynchronous properties (C#, Objective-C, Dart, probably many
others) typically leverage that concept for more than just simple
immutability - the concept of properties that behave differently when you
attempt to read and write is not typically a mere annotation/directive
instructing the compiler to enforce a rule, it's typically made possible
via support for accessors.

This might limit future options for the language, perhaps depending on how
it's implemented.

I hope it doesn't mean we can't have accessors at some point, in the
distant future.

In my opinion, all of these things go hand-in-hand: accessors, read-only,
property type-hints, as these are all essentially about defining and
enforcing constraints and making assertions about the state of a model.

I feel that this feature is a poor substitute for accessors, for example,
because this feature really applies only to immutable models - whereas a
feature such as accessors could be used equally to create immutable models,
but would permit us to move away from get/set-methods entirely, e.g. would
allow to write models with more consistent APIs, for example something like:

class Name {
public readonly $first;
public readonly $last;
public $full_name {
get { return "{$this->first} {$this->last}"; }
}
}

Something like that 

Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-11-20 Thread Rasmus Schultz
> if you've hired developers that care more about trends than your
application then you've hired the wrong developers.

A consistent, complete type-system is not a "trend".

In my experience, good developers notice things like inconsistency - and
they generally do not like it.

I am personally *not* about trends, and don't tend to count developers who
buy into hype as "good" developers - those would *not* be the developers
I'd be concerned about walking. We can hire developers like those again
easily.

> If every language is the same then what's the point of different
languages?

I'm not arguing "PHP should be more like X", I'm arguing for consistency
and completeness - an irrational fear of having certain similarities with
other languages really does not work as an argument against that.

Anyways, glad to hear Bob Weinland has been working on typed references and
the RFC is not dead :-)


On Sat, Nov 19, 2016 at 3:49 PM, Daniel Morris 
wrote:

> If every language is the same then what's the point of different
> languages? People use Scala and PHP for different things, if your
> developers are considering walking for that reason then they should
> evaluate whether they want to build things or whether they want to be
> trendy. Good (heck, great) developers will put to best use the tools
> they have available. Migrate to Go, and watch every one of them
> eventually complain about how they're having to check for err against
> every function call since functions return multiple values, have them
> migrate to Scala and watch their frustration as the time to change
> visibility is dropped significantly; if you've hired developers that
> care more about trends than your application then you've hired the wrong
> developers.
>
> --
> Daniel Morris
> dan...@honestempire.com
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] [RFC][Vote] Typed Properties

2016-11-19 Thread Rasmus Schultz
Heh, so, this week, a coworker of mine started using PHP 7, and he calls me
over, and he's like, "I don't get it, I had heard PHP 7 was supposed to
have type-hints now - it worked for return-types, but what am I doing
wrong, I can't seem to get this to work for properties?"

He actually had something like "public int $id" in a class-declaration on
his screen, and was genuinely confused - he simply assumed that would work,
since it worked for return-types. When I explained to him that, no, PHP 7
still isn't type-hinted, it's *more* type-hinted, but still not fully
type-hinted, he gave me the lemon-face. You know the one. Like you just ate
a lemon. Yeah.

I don't think there's a developer on my team and this point who isn't at
least checking out other languages in frustration with the lack of features
and consistency. I'm starting to feel like we're at risk of some of our
best, young developers walking, if somebody offers them a chance to work
with more "exciting" languages like Scala, Go, Dart, etc. - I'm not trying
to say that proper type-hinting is the whole answer, but I believe it would
go a long way towards consistency and the sense of completeness you get
from some of the competing languages, where these features were engineered
into the language from the design stage, rather than being added on a bit
at a time.

Any plans to revive this RFC or is it officially dead?


On Thu, Jun 23, 2016 at 11:08 PM, Pascal MARTIN, AFUP <
mail...@pascal-martin.fr> wrote:

> Le 10/06/2016 12:38, Joe Watkins a Ă©crit :
>
>>  The vote for typed properties has been restarted.
>>
>
> Hi,
>
> We, at AFUP, often tend to be on the "more static / strict types" side of
> things, and it remains this way for this RFC -- which means we would be +1
> for typed properties.
>
> A few noted this was not quite "the PHP way", while the majority felt this
> was in line with previous changes (like scalar type declarations, nullable
> types...) and could prove interesting for complex applications.
>
> Judging from where the votes are right now, I'm guessing this RFC will not
> pass, but, in any case, thanks for your work on this!
>
> There are more "yes" than "no", so maybe it will open a path towards
> something, maybe a bit different, in another future version...
>
> --
> Pascal MARTIN, AFUP - French UG
> http://php-internals.afup.org/
>
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] Allow Iterator to be used with current, next, reset, key functions

2016-10-30 Thread Rasmus Schultz
> What I am concerned with is the opt-out case of this functionality. What
> if I do not want that somebody misuses an unbuffered result set in such
> a way: selecting 1,000 records just to throw 998 away

In my opinion, that's a completely hypothetical use-case.

If I fetched 1000 records, most likely I'm doing something with those
1000 records.

If I happen to also be doing something special with the first or last
record, why should that require anything special from the collection
object itself?

If we're really this concerned about someone misunderstanding these
functions, I think honestly it would be better to not support
traversables at all - e.g. force them to use iterator_to_array()
instead, which makes it very obvious what's happening.

Perhaps that's a better solution altogether. It also fixes the case
where you accidentally traverse an open record-set twice, e.g. calling
first() and last() on the same iterable - that's not a problem case
you can fix, not even with an interface. In that case, the correct
thing is to fetch the records first, and/or adjust your query, depends
on the use-case, but accidentally iterating twice is likely never the
desired side-effect.

> Another case is every unsorted form of collection, what is first, what is 
> last?

Hypothetical. If it doesn't matter what's first or last, such as in an
unsorted form collection, why would you be calling the first or last
functions?

> How to you determine first and last if the keys of a traversable are objects?

They're the first and last items to come out of the traversable. Seems
pretty straight forward to me.

But either way, I think I'm changing my mind about this one.

And if the these functions support only arrays, then also the names
should probably be array_first() and array_last() for consistency with
other array-only functions.

Perhaps better to make people be explicit, rather than trying to hide
side-effects to achieve shorter syntax...


On Sun, Oct 30, 2016 at 2:14 PM, Fleshgrinder <p...@fleshgrinder.com> wrote:
> On 10/30/2016 1:59 PM, Rasmus Schultz wrote:
>> I think you misunderstand.
>>
>> I'm only suggesting that implementing first/last explicitly as an
>> optimization be optional.
>>
>> If you call first() or last() on a traversable that doesn't implement
>> this interface, it will simply traverse the first item or traverse to
>> the end.
>>
>> In other words, it'll always work, so it doesn't violate anything.
>>
>> As said, in a lot of cases, such as traversing a stream of database
>> records, there *is* no optimization you can make for last() because
>> that's not possible with the driver.
>>
>> So in that case, what you're proposing, is that all existing
>> traversables, such as DB adapters, shouldn't work with these functions
>> at all - everyone should have to go and implement this interface
>> first, even for traversable record sets where no optimization can be
>> made anyway and all you can do is actually fast-forward to the last
>> record by traversing the whole result set anyhow.
>>
>> The only thing you'll get by forcing implementation of this interface,
>> is no existing traversable will work with these functions.
>>
>> In addition, when everyone starts implementing this interface, those
>> libraries will lose backwards compatibility, since that interface will
>> not be available on older versions.
>>
>> All so you can force people to implement an interface that, in many
>> cases, contains redundant code that simply traverses the entire result
>> set to the last item and returns it, for no meaningful reason.
>>
>
> What I am concerned with is the opt-out case of this functionality. What
> if I do not want that somebody misuses an unbuffered result set in such
> a way: selecting 1,000 records just to throw 998 away. Your proposal is
> very appealing in many ways but the opt-out means that I now need to
> trigger a notice or throw an exception because there is no other way to
> disallow this functionality.
>
> Especially in the light of unbuffered result sets and generators which
> can be traversed only once.
>
> Another case is every unsorted form of collection, what is first, what
> is last? How to you determine first and last if the keys of a
> traversable are objects? Fail?
>
> There are too many open questions in this regard. It's easier with the
> primitive arrays because they have their limitations clearly defined
> (maps keep insert order).
>
> First and last only make sense for certain data structures but not for
> all. Implementing something that just works might work for 80 % but not
> for the rest and they have the problem now. I know that we have no means
> to express proper data structures but this will not make it better.
> Whether it makes it worse is another question that might help to decide.
>
> --
> Richard "Fleshgrinder" Fussenegger

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



Re: [PHP-DEV] Allow Iterator to be used with current, next, reset, key functions

2016-10-30 Thread Rasmus Schultz
I think you misunderstand.

I'm only suggesting that implementing first/last explicitly as an
optimization be optional.

If you call first() or last() on a traversable that doesn't implement
this interface, it will simply traverse the first item or traverse to
the end.

In other words, it'll always work, so it doesn't violate anything.

As said, in a lot of cases, such as traversing a stream of database
records, there *is* no optimization you can make for last() because
that's not possible with the driver.

So in that case, what you're proposing, is that all existing
traversables, such as DB adapters, shouldn't work with these functions
at all - everyone should have to go and implement this interface
first, even for traversable record sets where no optimization can be
made anyway and all you can do is actually fast-forward to the last
record by traversing the whole result set anyhow.

The only thing you'll get by forcing implementation of this interface,
is no existing traversable will work with these functions.

In addition, when everyone starts implementing this interface, those
libraries will lose backwards compatibility, since that interface will
not be available on older versions.

All so you can force people to implement an interface that, in many
cases, contains redundant code that simply traverses the entire result
set to the last item and returns it, for no meaningful reason.


On Sun, Oct 30, 2016 at 1:47 PM, Fleshgrinder <p...@fleshgrinder.com> wrote:
> On 10/30/2016 1:31 PM, Rasmus Schultz wrote:
>> On second thought, I agree with that - changing reset() and end()
>> doesn't make sense, because people know them and expect them to work
>> in a certain way. Likely a lot of people would actually continue to
>> use them with intermediary variables the way they do today. Better
>> to introduce a new pair of functions, since this will make it clear
>> when consumer code depends on the new behavior - if we update the
>> existing functions, that means you have to read code knowing which
>> version of these very common (and very old) functions you were
>> expecting to call.
>>
>> One thing though, since we have to introduce new functions, I would
>> not suggest these be array_first() and array_last(), but rather
>> simply first() and last(), and make then work with anything iterable,
>> not just arrays.
>>
>
> `first()` and `last()` are extremely generic names and I am still hoping
> to see nikic's scalar objects extension to land in core before 8. In
> this case one would always call `$x->first()` and `$x->last()`.
> Continuing with the `array_` prefix makes perfect sense to me, even if
> they accept `\Traversable` instances as well. We also expect `str_`
> prefixed functions to accept stringable objects, dont' we. It's just a
> prefix for grouping and not necessarily a restrictions regarding the
> types the function accepts.
>
> On 10/30/2016 1:31 PM, Rasmus Schultz wrote:
>>> Retrieving the first and last would mean to iterate all the
>>> results.
>>
>> Well, retrieving the last would - retrieving the first would mean
>> iterating only over the first result. For a lot of use-cases, and
>> unbuffered database results in particular, this is precisely what
>> you'd want.
>>
>>> An additional interface should be required for traversables in
>>> order to work with first and last.
>>
>> I think it would be great to have that as an option - for cases
>> where you can and want to optimize retrieval of the last item, but I
>> don't think it should be required? For example, in the case of an
>> unbuffered database query, there is likely no optimization that can
>> be made for last() in the first place, since the database
>> client/server are likely using a protocol that doesn't even allow you
>> to skip to the last result; in that case, requiring everyone to
>> implement a new interface, which does nothing, isn't meaningful.
>>
>
> Not requiring the interface means that we violate the Liskow's
> substitution principle, something I see too often in core and successful
> PHP software out there. What if a traversable does not want the first
> and last to be retrieved in this manner? Throw an exception? This
> violates the principle since it is not expected to behave in this way.
> Another possibility would it be to return null but then the question is,
> was null returned because the first or last element is null or because I
> cannot retrieve the first and last.
>
> Making it explicit is much better.
>
> --
> Richard "Fleshgrinder" Fussenegger

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



Re: [PHP-DEV] Allow Iterator to be used with current, next, reset, key functions

2016-10-30 Thread Rasmus Schultz
On second thought, I agree with that - changing reset() and end()
doesn't make sense, because people know them and expect them to work
in a certain way. Likely a lot of people would actually continue to
use them with intermediary variables the way they do today. Better to
introduce a new pair of functions, since this will make it clear when
consumer code depends on the new behavior - if we update the existing
functions, that means you have to read code knowing which version of
these very common (and very old) functions you were expecting to call.

One thing though, since we have to introduce new functions, I would
not suggest these be array_first() and array_last(), but rather simply
first() and last(), and make then work with anything iterable, not
just arrays.

> Retrieving the first and last would mean to iterate all the results.

Well, retrieving the last would - retrieving the first would mean
iterating only over the first result. For a lot of use-cases, and
unbuffered database results in particular, this is precisely what
you'd want.

> An additional interface should be required for traversables in order to work 
> with first and last.

I think it would be great to have that as an option - for cases where
you can and want to optimize retrieval of the last item, but I don't
think it should be required? For example, in the case of an unbuffered
database query, there is likely no optimization that can be made for
last() in the first place, since the database client/server are likely
using a protocol that doesn't even allow you to skip to the last
result; in that case, requiring everyone to implement a new interface,
which does nothing, isn't meaningful.


On Sun, Oct 30, 2016 at 1:07 PM, Fleshgrinder <p...@fleshgrinder.com> wrote:
> On 10/30/2016 12:45 PM, Nikita Popov wrote:
>> On Sun, Oct 30, 2016 at 12:24 PM, Rasmus Schultz <ras...@mindplay.dk> wrote:
>>
>>> With regards to deprecating array-functions that operate on the
>>> internal pointer - I'd like to just remind you of the fact that some
>>> of these functions, reset() and end() in particular, are often used
>>> not because someone cares about moving the internal pointer, but as a
>>> means of getting the first/last items of an array.
>>>
>>> If the internal pointers are removed, I'd like to suggest we improve
>>> the reset() and end() functions rather than removing them - there is
>>> an annoyance with these two functions presently: because they operate
>>> on the internal pointer, the force you to introduce often meaningless
>>> intermediary variables.
>>>
>>> That is, for example:
>>>
>>> $last = end(explode(",", $comma_separated_values));
>>>
>>> Doesn't work. One is forced to introduce a variable:
>>>
>>> $parts = explode(",", $comma_separated_values);
>>> $last = end($parts);
>>>
>>> If internal pointers are removed, maybe the reset() and end()
>>> functions could be made to actually work consistently? Whether applied
>>> to an expression or variable.
>>>
>>
>> Yeah, I've been thinking about this as well. reset() and end() do seem to
>> be the most commonly used IAP functions -- while nobody actually cares
>> about their effect on the IAP. The thing is, if we remove all other
>> functions that allow users to inspect the IAP, then we can simply change
>> reset() and end() to return the first/last element. As they would no longer
>> actually modify the array, they would no longer accept their argument by
>> reference, so end(explode(...)) would also become legal (and additionally,
>> they would no longer have to do a full copy of their argument, like they
>> currently sometimes need to do).
>>
>> Nikita
>>
>
> I think it makes much more sense to deprecate all of them and introduce
> new ones that work in the way we want them to for several reasons.
> `end()` and `reset()` would have to continue working as they do until
> the next major release since people who use them might rely on the way
> they work. This means in effect that nobody can make her PHP 7 code PHP
> 8 ready up front.
>
> Instead we could directly introduce `array_first()` and `array_last()`
> with the next feature release -- even if the others are not deprecated
> -- and everyone can update their code or at least use it in new code.
>
> Changing `end()` and `reset()` in PHP 7 is imho way to dangerous!
>
> Another often asked/proposed question is whether they should accept
> traversables. I think especially for these two functions it's not easy
> to simply accept any kind of traversable. Think of an unbuffered
> database result which is effectively a remote pointer. Retrieving the
> first and last would mean to iterate all the results.
>
> An additional interface should be required for traversables in order to
> work with first and last.
>
> --
> Richard "Fleshgrinder" Fussenegger

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



Re: [PHP-DEV] Allow Iterator to be used with current, next, reset, key functions

2016-10-30 Thread Rasmus Schultz
With regards to deprecating array-functions that operate on the
internal pointer - I'd like to just remind you of the fact that some
of these functions, reset() and end() in particular, are often used
not because someone cares about moving the internal pointer, but as a
means of getting the first/last items of an array.

If the internal pointers are removed, I'd like to suggest we improve
the reset() and end() functions rather than removing them - there is
an annoyance with these two functions presently: because they operate
on the internal pointer, the force you to introduce often meaningless
intermediary variables.

That is, for example:

$last = end(explode(",", $comma_separated_values));

Doesn't work. One is forced to introduce a variable:

$parts = explode(",", $comma_separated_values);
$last = end($parts);

If internal pointers are removed, maybe the reset() and end()
functions could be made to actually work consistently? Whether applied
to an expression or variable.



On Sat, Oct 29, 2016 at 10:06 PM, Nikita Popov  wrote:
> On Fri, Oct 28, 2016 at 2:43 PM, Levi Morrison  wrote:
>
>> On Wed, Oct 26, 2016 at 7:42 AM, David Lundgren 
>> wrote:
>> > Greetings,
>> >
>> > As suggested by several reviewers of a PR[1] I recently submitted, I'd
>> > like to get feedback on letting custom Iterators be used in the current,
>> > next, reset, and key functions. If this is something to move forward
>> > with, I'll need some help with the RFC process.
>> >
>> > Recent experiences trying to use these functions with a custom Iterator,
>> > and a bug[2], led me to try and fix this. BC will occur when an object
>> > implementing Iterator is passed to one of the functions, as the
>> > interface methods will be called, instead of returning the objects
>> > properties. The old behavior should be maintained for classes that do
>> > not implement Iterator.
>> >
>> > [1] https://github.com/php/php-src/pull/2176
>> > [2] https://bugs.php.net/bug.php?id=49369
>> >
>> > Thanks,
>> > Dave
>> > --
>> > David Lundgren
>> > dlundg...@syberisle.net
>> > 808.639.0365
>> > GPG: 0x26F54D7F
>> >
>> > --
>> > PHP Internals - PHP Runtime Development Mailing List
>> > To unsubscribe, visit: http://www.php.net/unsub.php
>>
>> I can't seem to recall specifics anymore but I do believe some people
>> would greatly prefer to remove the internal array pointer for
>> iteration and deprecate these functions. Maybe someone else can
>> remember more? Nikita and Bob, maybe?
>>
>
> Yeah, I'm one of those people. In PHP 7 the most important user of the IAP,
> foreach, was switched to use a more robust mechanism. I believe that at
> this point, the concept of an internal array pointer has outlived its
> usefulness and we should be working toward removing any APIs that publicly
> expose it, including each and the next/current/key family of functions. I
> will propose to deprecate each() in particular for PHP 7.2, because it is
> both more problematic and more useless than the others, but I'd like to see
> the others go away in the long term as well. If people want fine-grained
> control over array iteration, they should use an external iterator (aka
> ArrayIterator), not an internal one.
>
> Nikita

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



Re: [PHP-DEV] SQLite 3.14

2016-08-10 Thread Rasmus Schultz
On Wed, Aug 10, 2016 at 4:08 PM, Christoph M. Becker  wrote:

> Sounds reasonable, Anotol.  Thanks.  So I'm going to update 7.1+ ASAP.

Are you going to include any plugins?

I noticed today, SQLite has interesting optional features - in
particular, the "json1" plug-in looks interesting.

Both MySQL and Postgres have JSON features now, so it would be nice if
the supported file-database also had this feature.

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



Re: [PHP-DEV] Function auto-loading

2016-08-09 Thread Rasmus Schultz
On Tue, Aug 9, 2016 at 6:17 PM, Rowan Collins  wrote:

>> In other words, calls to substr() does not trigger the resolve - a
>> statement like "use function substr" on the other hand, does.
>
> Ah, I see. The problem with that is, you still have to explicitly list every
> function you're going to use, so you might as well just use require_once, or
> call "load_function('substr')" directly.

Well, no - there is still the issue of file names and paths becoming a
dependency, besides issue of having to locate the file in the first
place.

So there is still very much a purpose to this.

Importing all classes with use-statements is good practice anyhow, and
- it forces you to document at the top of your file which elements
you're referencing outside of the local namespace. Of course, that's
opinion, but it's a common opinion - you don't see too much code in
the wild with inline qualified class references, most everyone has a
leading set of use-statements in every file.

Actually, now that I think of it, for that reason, I might actually be
okay with only qualified references triggering auto-loading after all
- this would never become an issue at all, because I'd qualify
everything with use-statements anyhow.

Though I do think it would be somewhat easier to *explain* this
feature, if it was simply triggered by the use-statement, not by the
circumstance of whether the name is or isn't qualified, because it's
not always obvious from looking at the code - you'd have to look at
the use-statements first and then correlate those with function-calls
and figure it out, every time you look at a file. That mental overhead
is eliminated by just having the use-statement trigger auto-loading.

Also, come to think of it, triggering the auto-loader could still be
deferred, for performance reasons, even if the use-statement is what
triggers is - so it wouldn't aggressively trigger the auto-loader when
the use-statement is encountered, but rather the first time the a
function imported with a use-statement is called. That would be more
consistent with how class resolution works.

I think maybe this could work after all??

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



Re: [PHP-DEV] Function auto-loading

2016-08-09 Thread Rasmus Schultz
On Tue, Aug 9, 2016 at 12:04 AM, Rowan Collins  wrote:

> I don't quite follow what you're suggesting here. When does this "function
> resolver" get called?

I'm suggesting the use-statement be the trigger, rather than actually
calling the function.

In other words, calls to substr() does not trigger the resolve - a
statement like "use function substr" on the other hand, does.

> Why does returning a callable rather than just
> defining the function help with the problems we've been discussing?

For some reason, at the time, I thought, this way the function would
indicate whether it resolved a request for "foo\bar" as "foo\bar" or
"bar", but that's probably false... likely the registered function
would get called twice by the engine, first trying for the namespaced,
then if that doesn't resolve, for the global function.

> we need "namespace
> autoloading", which in practice means autoloading any of the items you can
> put in a namespace.

Good point.

So maybe what I'm really proposing is just simply a change to
functionality - so that function and constant references do not
trigger auto-loaders, but instead the "use const" and "use function"
statements do.

I guess this deviates from the way auto-loading works for classes, too
- just in a different way... so maybe it's not much better.

Come to think of it, maybe it's worse, because this would aggressively
trigger auto-loading for functions that might never get called, so,
hmm...

I think, in practice, it's not going to work much differently from the
other proposed work-around though - if only qualified references
trigger auto-loading, then this would trigger auto-loading:

\foo\bar();

And this would too:

use foo\bar;

bar();

But this would not:

bar();

And that could get pretty confusing, since the unqualified call site
looks identical to the qualified call site.

Ugh.

Well, I guess this is what lead to a discussion about a breaking
change to the name resolution rules?

Is there an RFC detailing that idea? Or what was the title of that
discussion? I'd like to read up.

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



Re: [PHP-DEV] Function auto-loading

2016-08-08 Thread Rasmus Schultz
On Mon, Aug 8, 2016 at 10:54 PM, Lester Caine  wrote:
> I can understand a little the overwhelming desire to wrap everything in
> it's own set of name spaces, but is that REALLY essential to make PHP
> 'work better'. What is wrong with a simple 'include_once' of the library
> you want to use globally across all the code?

Doesn't work with Composer packages, because you can't (and aren't
supposed to) know where a package is installed.

That is, when I'm running the test-suite of my package, the Composer
project is the root folder of that package - but when the package is
being consumed by another project, it's installed in a sub-folder in
that project's "vendor" folder.

The whole point of auto-loading is you don't need to know where things
are installed - a class will simply auto-load, regardless of whether
or not the package is the root project package of the consuming
package. Composer takes care of the bootstrapping.

If we didn't care about that, we wouldn't need auto-loading at all. Or
in other words, your argument works against auto-loading of functions
and classes equally.

What's wrong with a simple require/include statement when you need a
class? Nothing per se. It's horribly inconvenient. The main reason
you're not feeling the same inconvenience when it comes to functions,
is likely because you avoid using them - which is likely because using
functions isn't practical. Likely because they don't auto-load, like
functions. So we use classes as pseudo-namespaces, because they can
auto-load - but that's not what classes are for; you could just as
well argue the language shouldn't have functions at all, then.

In a nut-shell: functions are inconvenient because they don't
auto-load, so we don't use functions, so we don't need auto-loading;
but that's a circular argument.

Of course we need functions to auto-load. For all the same reasons we
need classes to auto-load. Nobody wants to stop and have to figure out
in which file a function is located before they can call it, anymore
than they want to do so for classes. Nobody wants breaking changes in
50 different files because they renamed a file or decided to
split/join some functions across some files.

The auto-loading requirement for functions is the same as for classes.
There's no difference.

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



Re: [PHP-DEV] Function auto-loading

2016-08-08 Thread Rasmus Schultz
Aren't stream wrappers already lazy-loaded?

e.g. stream_wrapper_register("random", RandomStreamWrapper::class) does not
afaik actually load anything.

Making stream wrappers directly registerable from e.g. "composer.json"
should be a near-trivial thing to implement, and would make them
effectively "autoload" - I imagine it's no more costly to pre-register the
protocol/class-name than e.g. pre-registering some other form of
auto-loader?


On Mon, Aug 8, 2016 at 10:23 PM, Davey Shafik <da...@php.net> wrote:

> On Mon, Aug 8, 2016 at 1:15 PM, Rasmus Schultz <ras...@mindplay.dk> wrote:
>
>> > Unfortunately, function name resolution has this quirk that class name
>> resolution doesn't, so something's got to give.
>>
>> I suppose.
>>
>> Well, then, how about making the feature work consistently for all
>> functions, by coupling it directly to the "use function" statement?
>>
>> In other words, the feature changes from being strictly about auto-loading
>> functions, to instead resolving an imported function - so it would be
>> triggered by the "use function" statement only, rather than by the use of
>> the function, and the resolved function pertains only to the scope of the
>> file.
>>
>> A function resolver would simply need to return a callable:
>>
>> register_function_resolver(function ($name) {
>> if ($name === "html") {
>> return function ($str) {
>> return htmlspecialchars($str, ENT_HTML5);
>> };
>> }
>>
>> if (substr($name, 0, 5) === "iter\\") {
>> require_once VENDOR_PATH."/nikic/iter/src/bootstrap.php";
>> return $name;
>> }
>> });
>>
>> This mechanism is probably a lot easier to explain and understand - and
>> works equally for global or namespaced functions.
>>
>> It also lets you potentially do other weird shit, like overriding
>> var_dump() or hooking into certain function calls - which could enable you
>> to do a bunch of evil, but I'm not really big on complicating features
>> solely to keep users from doing harm; simpler language features tend to
>> allow you to do more stuff - good or evil.
>>
>> Likely the 99% use-case is simply for Composer to bootstrap your packages
>> for you, and this feature will permit you to do that.
>>
>> Okay, so it doesn't deal with namespaced constants, and maybe this is me
>> being opinionated, but who's going to import constants one by one?
>> Constants are usually better off grouped together in a class. Although I
>> don't suppose there's any reason this concept couldn't be expanded to work
>> for constants as well, for completeness at least - though I have doubts
>> that very many people would care...
>>
>> Anyways, just spitballing here :-)
>>
>>
>> On Mon, Aug 8, 2016 at 7:54 PM, Rowan Collins <rowan.coll...@gmail.com>
>> wrote:
>>
>> > On 08/08/2016 18:03, Levi Morrison wrote:
>> >
>> >> If not, I don't see why we ever need to be able to autoload global
>> >> functions. "You want autoloading? Put it in a namespace." Like I
>> >> say, that leaves the very small edge case of a single namespace
>> >> spanning multiple files, and an autoloader implementation able to
>> >> include one of them when a function is called from another.
>> >>
>> >>
>> >> I'm not sure why you would think a single namespace spanning multiple
>> >> files is a "very small edge case". I disagree. Here are some libraries
>> I
>> >> am aware of *off the top of my head* that use functions the same
>> >> namespace across multiple files:
>> >>
>> >>   * https://github.com/nikic/iter
>> >>   * https://github.com/lstrojny/functional-php
>> >>
>> >> As well as several of my personal projects. I do not think this is a
>> >> "very small edge case."
>> >>
>> >
>> > The "iter" example looks a long way from being autoloadable whatever we
>> > supported, but the example of one-function-per-file is definitely
>> relevant,
>> > so I stand corrected.
>> >
>> > After a bit of clicking, I even managed to find a line which would fail
>> to
>> > autoload under the proposed limitation:
>> >
>> > https://github.com/lstrojny/functional-php/blob/master/src/
>> > Functional/CompareObje

Re: [PHP-DEV] Function auto-loading

2016-08-08 Thread Rasmus Schultz
> Unfortunately, function name resolution has this quirk that class name
resolution doesn't, so something's got to give.

I suppose.

Well, then, how about making the feature work consistently for all
functions, by coupling it directly to the "use function" statement?

In other words, the feature changes from being strictly about auto-loading
functions, to instead resolving an imported function - so it would be
triggered by the "use function" statement only, rather than by the use of
the function, and the resolved function pertains only to the scope of the
file.

A function resolver would simply need to return a callable:

register_function_resolver(function ($name) {
if ($name === "html") {
return function ($str) {
return htmlspecialchars($str, ENT_HTML5);
};
}

if (substr($name, 0, 5) === "iter\\") {
require_once VENDOR_PATH."/nikic/iter/src/bootstrap.php";
return $name;
}
});

This mechanism is probably a lot easier to explain and understand - and
works equally for global or namespaced functions.

It also lets you potentially do other weird shit, like overriding
var_dump() or hooking into certain function calls - which could enable you
to do a bunch of evil, but I'm not really big on complicating features
solely to keep users from doing harm; simpler language features tend to
allow you to do more stuff - good or evil.

Likely the 99% use-case is simply for Composer to bootstrap your packages
for you, and this feature will permit you to do that.

Okay, so it doesn't deal with namespaced constants, and maybe this is me
being opinionated, but who's going to import constants one by one?
Constants are usually better off grouped together in a class. Although I
don't suppose there's any reason this concept couldn't be expanded to work
for constants as well, for completeness at least - though I have doubts
that very many people would care...

Anyways, just spitballing here :-)


On Mon, Aug 8, 2016 at 7:54 PM, Rowan Collins <rowan.coll...@gmail.com>
wrote:

> On 08/08/2016 18:03, Levi Morrison wrote:
>
>> If not, I don't see why we ever need to be able to autoload global
>> functions. "You want autoloading? Put it in a namespace." Like I
>> say, that leaves the very small edge case of a single namespace
>> spanning multiple files, and an autoloader implementation able to
>> include one of them when a function is called from another.
>>
>>
>> I'm not sure why you would think a single namespace spanning multiple
>> files is a "very small edge case". I disagree. Here are some libraries I
>> am aware of *off the top of my head* that use functions the same
>> namespace across multiple files:
>>
>>   * https://github.com/nikic/iter
>>   * https://github.com/lstrojny/functional-php
>>
>> As well as several of my personal projects. I do not think this is a
>> "very small edge case."
>>
>
> The "iter" example looks a long way from being autoloadable whatever we
> supported, but the example of one-function-per-file is definitely relevant,
> so I stand corrected.
>
> After a bit of clicking, I even managed to find a line which would fail to
> autoload under the proposed limitation:
>
> https://github.com/lstrojny/functional-php/blob/master/src/
> Functional/CompareObjectHashOn.php
>
> > return compare_on($comparison, $keyFunction);
>
> Although interestingly, at the top of the file there is a (technically
> unnecessary) "use function Functional\compose;" If there was a "use
> function Functional\compare_on;" as well, we'd be fine. (The function name
> would then become qualified at compile time and trigger autoloading at run
> time.)
>
>
> On 08/08/2016 18:06, Rasmus Schultz wrote:
> > Unless there's a demonstrated, critical performance issue with
> > auto-loading of global functions, please, let's not cripple this feature
> > with inconsistencies from the get-go!
>
> Sure, we could try to measure it, but remember that it's not just the
> engine code that has the extra cost, it will actually call a userland
> function every time you use a global function from inside a namespace if
> you don't add a leading "\". That userland function will probably do a
> bunch of string comparisons before deciding it's not interested, and may
> even try to stat a file or two. Those are really expensive operations, so I
> think it's a long way from "micro-optimisation".
>
> Unfortunately, function name resolution has this quirk that class name
> resolution doesn't, so something's got to give.
>
>
> Regards,
> --
> Rowan Collins
> [IMSoP]
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] Function auto-loading

2016-08-08 Thread Rasmus Schultz
> If not, I don't see why we ever need to be able to autoload global
functions

Well, for consistency.

For one, if you're refactoring a global function to a namespaced one, this
inconsistency is going to be surprising.

In general, any inconsistency in a language is surprising. Why only
non-global functions can autoload, is going to require a longer
explanation. And that's bad.

If we support auto-loading only for namespaced functions, we're actively
favoring (potentially micro-) performance over consistency.

I use global functions. I know that's not popular, but it's a language
feature, and I use it - for things like test-frameworks and global view
helper-functions.

Single namespace spanning multiple files is also a case for me - that's not
a decision we should make; likely, a PSR and Composer auto-loading features
will drive those decisions. One should have the freedom to add a new
function to an existing namespace, and make that function auto-load, while
packaging that function as a separate optionally-installable package.

I can't see the introduction of arbitrary restrictions or limitations
leading to anything good, language-wise.

Unless there's a demonstrated, critical performance issue with auto-loading
of global functions, please, let's not cripple this feature with
inconsistencies from the get-go!


On Mon, Aug 8, 2016 at 6:46 PM, Rowan Collins 
wrote:

> On 08/08/2016 17:00, Levi Morrison wrote:
>
>> I think saying "add a backslash in front of your function names to
>> avoid them being slow" will just lead to lots of "lol wtf php sux".
>>
>>
>> They'll say the same when function and class autoloading don't work the
>> same way anyway. I think unifying their behavior over time is the best
>> solution forward. Yes, I'm talking about a BC break eventually, but the
>> suggestion to autoload only fully qualified function names could buy us
>> the time to make that BC break less severe.
>>
>
>
> Do you mean eventually changing the name resolution rules for functions to
> match those for classes? I wasn't around at the time it was discussed, and
> if we were adding them now would be tempted to say the leading \ should
> always be mandatory, just like it is for classes. But since we have what we
> have, I don't see that big an advantage to changing it.
>
> If not, I don't see why we ever need to be able to autoload global
> functions. "You want autoloading? Put it in a namespace." Like I say, that
> leaves the very small edge case of a single namespace spanning multiple
> files, and an autoloader implementation able to include one of them when a
> function is called from another.
>
>
> Regards,
> --
> Rowan Collins
> [IMSoP]
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] Function auto-loading

2016-08-07 Thread Rasmus Schultz
Of course calling e.g. strpos() should not trigger the auto-loader
repeatedly - can we cache the information that the auto-loader was
attempted once during the current script execution? so that e.g. only the
first call to strpos() triggers the auto-loader?

I suppose it would still happen once for every namespace from which
strpos() gets called, so maybe this optimization doesn't help much.

I guess I'd say, benchmark it before making assumptions? Maybe the
performance hit turns out to be negligible in practice. Hard to say.

If a performance hit is inevitable, but marginal, I hope that we do not let
micro-benchmarks stand in the way of improving the language?

With PHP 7, the language is in many ways almost twice as fast as it was
before. I think it's fair to say, PHP has problems that are much bigger
than performance - to most developers, performance is not a pain point
anymore, if it was before PHP 7.

I wish that I could change your focus from performance concerns to actually
focusing on the language itself.

It seems that me that recent performance improvements have become somewhat
of a bottleneck that *prevents* new features and (worse) missing features
from completing and improving the language?

The performance improvements could just as well be viewed as a factor that
creates new elbow room for new features and language improvements, which,
long term, likely have much more value to more developers than the
performance of micro-benchmarks.

At the end of the day, for like 9 our of 10 projects, PHP's core
performance is not the bottleneck - things like database queries are. The
cost of developing a project is also generally unrelated to core
performance of the language. Hardware gets cheaper and faster every day. So
who or what are we optimizing for?

I don't mean to get too side-tracked from the original conversation here,
but we should be designing for developers - not for machines. The language
is more than fast enough for what most developers need it for - and still
nowhere near fast enough for, say, a JSON or XML parser, the kind of things
that require C or assembly level performance, and I really don't believe
there's a substantial segment of use-cases that fall in between - for most
things, either you need performance that PHP can't get near, or you need
language features and convenience that low-level languages can't deliver.

We're not competing with C - and if we're competing with other scripting
languages on performance, we're already in a pretty good position, and
people who select a scripting language aren't basing their choice on raw
performance in the first place; if that was their concern, they'd pick C.

We should focus on competing with other scripting languages on features,
convenience, productivity, etc. - if our main concern is competing on
low-level concerns like performance, those concerns will override the
points that really matter to developers who choose a high-level scripting
language, and we will lose.


On Sun, Aug 7, 2016 at 1:29 PM, Nikita Popov <nikita@gmail.com> wrote:

> On Sun, Aug 7, 2016 at 1:19 PM, Rasmus Schultz <ras...@mindplay.dk> wrote:
>
>> I'd really like to see the function auto-loading proposal revived and/or
>> possibly simplified.
>>
>> The fact that functions are hard (in some cases impossible) to reach by
>> manually issuing require/include statements is, in my opinion, half the
>> difficulty, and a much more deeply rooted language problem exacerbating
>> what should be trivial problems - e.g. install a Composer package, import
>> (use) and call the functions.
>>
>> Looks like a fair amount of work and discussion was done in 2013 on this
>> RFC:
>>
>> https://wiki.php.net/rfc/function_autoloading
>>
>> There was a (now stale) proof of concept implementation for the parent RFC
>> as well:
>>
>> https://wiki.php.net/rfc/function_autoloading2
>>
>> What happened?
>>
>> It looks like the discussion stalled mostly over some concerns, including
>> reservations about performance, which were already disproved?
>>
>> One issue apparently was left unaddressed, that of whether a call to an
>> undefined function should generate an auto-load call to a namespaced or
>> global function - I think this would not be difficult to address: trigger
>> auto-loading of the namespaced function first, check if it was loaded, and
>> if not, trigger auto-loading of the global function.
>
>
> I feel like the problem here did not get across properly. Calling the
> autoloader if a global function with the name exists will totally kill
> performance. This means that every call to strpos() or any of the other
> functions in the PHP standard library will have to go through the
> autoloader first, unless people use fully qualified names (which,
> currently, they don

[PHP-DEV] Function auto-loading

2016-08-07 Thread Rasmus Schultz
I'd really like to see the function auto-loading proposal revived and/or
possibly simplified.

The fact that functions are hard (in some cases impossible) to reach by
manually issuing require/include statements is, in my opinion, half the
difficulty, and a much more deeply rooted language problem exacerbating
what should be trivial problems - e.g. install a Composer package, import
(use) and call the functions.

Looks like a fair amount of work and discussion was done in 2013 on this
RFC:

https://wiki.php.net/rfc/function_autoloading

There was a (now stale) proof of concept implementation for the parent RFC
as well:

https://wiki.php.net/rfc/function_autoloading2

What happened?

It looks like the discussion stalled mostly over some concerns, including
reservations about performance, which were already disproved?

One issue apparently was left unaddressed, that of whether a call to an
undefined function should generate an auto-load call to a namespaced or
global function - I think this would not be difficult to address: trigger
auto-loading of the namespaced function first, check if it was loaded, and
if not, trigger auto-loading of the global function. Most likely a PSR
along with Composer auto-loading features will favor a best practice of
shipping packages with namespaced functions only, so the performance
implications of checking twice would be negligible in practice.

Being basically unable to ship or consume purely functional packages leaves
the functional side of the language largely an unused historical artifact,
which is sad. Keeping things functional and stateless often lead to more
predictable and obvious code - I think the absence of good support for
functions encourages a lot of over-engineering, e.g. developers
automatically making everything a class, not as a design choice, for the
sole reason of being able to ship and reuse what should be simple functions.

This RFC looks pretty solid to me.

What will it take to get this rolling again?


Re: [PHP-DEV] [RFC][VOTE] New operator (short tag) for context-dependent escaping

2016-08-07 Thread Rasmus Schultz
Looks like it's unanimously a No.

Michael, don't be discouraged - I think that everyone agrees that there is
a problem to be solved, it's just that no one except you thinks this is a
good solution; many of us are of the opinion that it's not a solution that
really addresses the problem at all: you haven't eliminated the choice of
whether or how to escape something, you've merely changed the scope of that
choice - into global state, which clearly isn't popular.

I encourage you to keep thinking about this problem, but you should explore
entirely different directions - rethink and rephrase the problem, get to
the core of it, and a different angle on the problem might reveal itself.


On Sat, Jul 30, 2016 at 5:09 PM, Michael Vostrikov <
michael.vostri...@gmail.com> wrote:

> Hello. The RFC 'New operator (short tag) for context-dependent escaping' is
> now in voting phase.
>
> https://wiki.php.net/rfc/escaping_operator
>
> This RFC introduces new short tag/operator, which will perform echo with an
> automatic call of escaping function.
> Voting is open till August 6, but it can be prolongated if you will decide
> that this is too small voting time for such a change.
> Voting requires 2/3 support.
>
> Thank you for voting.
>


Re: [PHP-DEV] [RFC] New operator for context-dependent escaping

2016-07-30 Thread Rasmus Schultz
> the problem IS NOT that we don't have a solution
> The problem IS that developer
> must call these functions everywhere manually.

What you don't seem to get, is your proposal doesn't change that fact?

It changes the syntax and means by which you select and call the function,
but it still requires the same choice and the same due diligence - and
thereby doesn't truly change anything.

This new tag will not simply replace  because you still need to
output HTML sometimes.

What you've coined "context" is really just a pseudo function-call - it
does not automatically establish context, and if I have to specify the
context, I'm really just specifying the function I'd like to call;
specifying the right "context" requires the exact same choice and diligence
as selecting the right function, all this does is wrap things in another
layer of complexity and blur things out even more. At least, with a
function call, I can tell which function is going to be called - rather
than digging through an extra facility that takes, essentially, a function
name, and calls it for me.

In my view, this only complicates things - it somewhat changes the problem,
but doesn't actually solve the problem...


On Sat, Jul 30, 2016 at 8:06 AM, Michael Vostrikov <
michael.vostri...@gmail.com> wrote:

> > The aim in my mind would be to make escaping easier to do right, for
> people who aren't already using a framework or templating engine with its
> own solution.
> > The current implementation doesn't seem to share these priorities; it
> feels like a building block for framework developers, who probably have
> their own solutions already.
>
> No! You don't understand what I'm trying to explain. This feature will be
> useful for ALL applications without template engine - frameworks, CMS,
> custom core. You say that frameworks have their own solutions already. But
> the problem IS NOT that we don't have a solution. PHP already has built-in
> function htmlspecialchars(), Yii has Html::escape(), Zend has
> $this->escape(). This is not the problem. The problem IS that developer
> must call these functions everywhere manually.
>
> 
> 
> name) ?>
> 
> 
> description) ?>
> 
> 
> age) ?>
> 
> 
> position->name) ?>
> 
> 
> group->name) ?>
> 
> 
> organisation->address) ?>
> 
> 
>
> This is the same as calling constructor manually after every 'new'
> statement: (new User)->__construct(...), (new Profile)->__construct(...).
> We have special function '__construct', which is called automatically. I
> suggest similar way for escaping. And because we cannot set the same magic
> function name for all applications I suggest to do this by registering a
> callable.
> This is not intended for people who don't have escaping functions, this is
> intended for people who already have escaping functions. RFC suggests the
> way how to call these functions automatically. And people who don't have
> escaping function may define it once, and it also will be called
> automatically.
>
>
>
> > - you can define automatic escaping for a whole file or a block within a
> file
> > - there is an extra filter to skip the automatic escaping (not the same
> as unescaping)
> > - the above can be done with any "context", but the default is HTML
> > - a "context" is not just the argument to a single all-powerful "escape"
> function; you can register a new context by name, > without reimplementing
> any of the existing functionality
> > - other template functions can say that their output shouldn't be
> escaped, or that their input should be pre-escaped
> > - other functionality of the system is aware of these notions, and
> designed to behave sensibly
>
> > I don't think there's any way PHP can ever reach that level of
> sophistication, because most of the language knows nothing about "context";
> the feature we build in is only ever going to be a simple short-hand for
> some basic function calls.
>
> Almost all of these points can be done with the system described in the
> RFC. Application can allow or restrict new contexts (without reimplementing
> any of the existing functionality). Any behavior can be defined in
> userland, we just need a point of extension.
>
>  class CsvTemplate
> {
> protected $escapers = [];
>
>
> function render()
> {
> set_escape_handler([$this, 'escape']);
> include $this->templateFile;
> restore_escape_handler();
> }
>
> function escape($str, $context = 'csv')
> {
> switch ($context) {
> case 'csv':
> return $this->escapeCsv($str);
> break;
>
> case 'raw':
> return $str;
> break;
>
> default:
> if (isset($this->escapers[$context])) {
> return call_user_func($this->escapers[$context], $str);
> }
>
> throw new Exception('Unknown context');
>   

Re: [PHP-DEV] optionally return class name from gettype

2016-07-30 Thread Rasmus Schultz
I agree, an argument that essentially turns it into a different function is
not a good practice.

Suggestions for a function-name?

typeof() or vartype() maybe?


On Fri, Jul 29, 2016 at 8:17 PM, Niklas Keller  wrote:

> >
> > Niklas Keller wrote:
> > > I'm not sure on the boolean through, I think a new function might be
> > better.
> >
> > In this point I desagree.
> > I think that boolean is the best way, mainly to avoid a new function
> > on userland.
> > It's like an "extension" for gettype(), and make senses just extend it.
>
>
> The issue is that it's not clear what this boolean means just from reading
> the code.
> If you follow Clean Code, you shouldn't have something like that, only in
> very, very rare cases.
>


Re: [PHP-DEV] [RFC] New operator for context-dependent escaping

2016-07-28 Thread Rasmus Schultz
Just a thought, but I can't help thinking that "improved escape facilities
and syntax" are a mere patch for a more than superficial problem.

The problem of differentiating HTML strings, which to not require escaping,
from other string, which do, could actually be viewed as a deeper problem,
which is the inability to tell string types apart.

I mean, there are many different types of strings - text, HTML, URLs,
e-mail addresses, UUIDs, etc.

The surface problem is that user has to know whether she's dealing with a
text or HTML string. But you could view that as a symptom of the inability
to designate, at the source, what type of string you're providing.

For example, compare this:

class ProductView
{
/** @var string product name as plain text, remember to escape this
*/
public $product_name;

/** @var string product description as HTML, do not escape this */
public $description;
}

With something (completely ficticious) like, say:

typedef HTML extends string;

class ProductView
{
/** @var string product name */
public $product_name;

/** @var HTML product description */
public $description;
}

And a more intelligent escape function, like:

function html($str) {
return $str instanceof HTML ? $str : htmlspecialchars($str);
}

This removes one source of error - the user can now safely apply the html()
function to any string, without having to know if the string is just a
string or HTML. (yeah, I know about the $double_encode switch for
htmlspecialchars() but that's actually just another example of a
work-around to the same, deeper problem.)

A feature like this is more general-purpose, and potentially solves many
other related problems, such as recognizing the difference between ints or
UUIDs with different intent, e.g. being identifiers for different entities.

My main point is that the proposed feature attempts to fix a problem that
applies to one use-case - templates - whereas looking deeper and fixing
problems, or adding features that work across the entire language for many
use-cases, tends to add more value and, in the long run, less complexity.

Usually, a deeper, more general feature will enable users to create
solutions, rather than fixing each of their problems with surface
solutions, one at a time, until the language becomes a crazy colorful
cacophony of solutions, rather than tools to *create* solutions.

Just my perspective...


On Thu, Jul 28, 2016 at 11:48 AM, Rowan Collins 
wrote:

> On 28/07/2016 10:39, Thomas Bley wrote:
>
>> creating an e() function can be a BC break if people already have an e()
>> function in their code.
>> The name e is ambiguous to me, is it escape, error, encrypt?
>>
>> You are free to provide a better rfc, but having e() being optional will
>> also make security optional.
>>
>
> I wrote an entire e-mail setting out what I think should be the aims of
> the feature, and you've picked on a single sentence that said that an e()
> function would fulfil *most* of those aims. At no point did I say "an e()
> function is the perfect solution". You are attacking a straw man.
>
> I'm not going to get into a back and forth on what "optional" means,
> either. I've stated what I think is important, and will leave it there.
>
>
> Regards,
> --
> Rowan Collins
> [IMSoP]
>
>
>
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] Pipe Operator v2

2016-07-23 Thread Rasmus Schultz
FWIW, I've read the manual page for the Hack page, and the RFC, a couple of
times now, and I simply don't understand it.

Are most PHP developers going to understand this feature, the meaning of
$$, and when/how to use this?

Are they going to be able to read code written in this way?

To your knowledge, are there any other languages where this feature is
found, or is it another one of those exotic features currently found in
Hack and nowhere else? (I know a bunch of languages, and this feature
doesn't ring any bells.)

How does this feature compare with the cascade operator more commonly found
in other languages?

I mean, maybe it's just me, because I'm familiar with the cascade operator
from other languages - but it seems simpler, more intuitive, easier to pick
up, and appears to solve most of the same problems? If so, perhaps it would
be right to consider the cascade operator as an alternative to this feature.

I know that Hack may be closer in nature to PHP than some other languages,
but if someone is familiar with both, likely they're not coming from Hack
and moving to PHP, they're likely moving from PHP to Hack, so language
similarity might not be the best argument for referencing Hack on this
point, as opposed to referencing other languages...

It seems to me, the main difference between the pipe operator and a cascade
operator, is the anonymous context variable $$ created by the pipe operator
- I think, partially, this is what makes those expression hard to read; the
context changes (or does it?) along the way, but the (nameless) symbol used
to reference those objects, in the same expression, are identical.

Rather than writing extremely long expressions, as demonstrated in the RFC,
I think, personally, if this feature were introduced, I'd lean more on
intermediary variables, with names, that clarify the meaning - referencing
a bunch of intermediaries with a nameless variable doesn't help readability
at all, in my opinion.

In contrast, I have no issue reading expressions with the cascade operator;
again, maybe that's just because I'm familiar with that operator from other
languages, but I don't think the nameless $$ variable helps readability or
understanding.

Just my two cents.


On Fri, Jul 22, 2016 at 5:54 PM, Larry Garfield 
wrote:

> On Wed, Jul 20, 2016, at 11:37 PM, Sara Golemon wrote:
>
> > > However, the introduction discusses fluent chained methods of objects,
> and
> > > states " This RFC aims to improve code readability by bringing fluent
> > > expressions to functional and OOP libraries not originally designed
> for the
> > > task."  The examples, however, all seem to be centered around
> procedural
> > > calls.  (A static method call is the same thing as a procedural
> function
> > > call in this respect.)  When dealing with methods on an object, it
> seems it
> > > wouldn't offer much.
> > >
> > In this context, I'd argue instance method calls aren't much different
> > from static method calls either, but I wanted to avoid too many
> > abstract/contrived examples.
> >
> > I suppose one might do something like:
> >
> >  return $this->loadConfig()
> > |> $arg->useConfig($$)
> > |> $this->loadUser($$)
> > |> array_merge($$, $this->userDefaults);
> >
> > But the PSR7 example is already contrived as it is.
> >
> > > This other recent discussion/proposal for a "Cascade" operator seems
> like it
> > > would handle the OOP/method case much better:
> > >
> > > http://news.php.net/php.internals/94466
> > >
> > > Note: I am not suggesting one is a substitute for the other; rather,
> that
> > > they are complementary by addressing different parts of the problem
> space,
> > > and the Pipe RFC should likely not emphasize OOP usage potential as I
> see
> > > not a great deal there.  I am still in favor of it, but let's not
> over-state
> > > its use cases.
> > >
> > Fair enough.  They certainly complement one another and I wouldn't
> > argue either is a one-job-fits-all solution.  I wasn't trying to
> > emphasize OOP usage so much as include it as applicable.  I think we
> > might actually be agreeing in principle even if we're diverging in our
> > word choices. :)
>
> I agree.  I'm entirely on board with the feature; more just critiquing
> the RFC intro text, which mentions OOP fluency as a use case, which I
> think is an over-reach.  It's a useful enough feature even without
> talking about that, and it seems we agree that the syntax when used with
> methods is a bit awkward.
>
> > P.S. - I'm totes going to make that a secondary voting choice now.
> > Name the token, 50% majority wins.
>
> :-)
>
> --Larry Garfield
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] [RFC] New operator for context-dependent escaping

2016-07-20 Thread Rasmus Schultz
This is a really good point, Marco.

Of course, this would be much cleaner with a set of functions, since $this
(whatever it is) is not truly a dependency for any of these functions -
they're likely sharing no context or state; they've likely been placed in
the class solely to make them available to the template, which is a
work-around creating a class dependency for no real reason.

Now, if we could autoload functions.. :-)


On Wed, Jul 20, 2016 at 8:30 PM, Marco Pivetta  wrote:

> The syntax is weird as heck.
>
> That said, frameworks without templating engine already have escaping
> helpers, for example:
> escapeHtml($value); ?>
> escapeHtmlAttr($value); ?>
> escapeJs($value); ?>
> escapeCss($value); ?>
>
> I don't see what is hard in using that syntax, plus it's not a global
> registry.
>
> Marco Pivetta
>
> http://twitter.com/Ocramius
>
> http://ocramius.github.com/
>
> On Wed, Jul 20, 2016 at 8:17 PM, Michael Vostrikov <
> michael.vostri...@gmail.com> wrote:
>
> > > Personally I don't know any developer who is using raw php in project
> > without template engine
> >
> > Zend, Yii, various CMS like Wordperss, internal business-applications -
> in
> > many cases such projects don't have a template engine.
> > I usually work with Yii and internal applications on custom engines. This
> > is the reason why I raised this question.
> > By the way, the syntax is not weird. It is just . How
> to
> > use $var2 is fully up to application.
> >
>


Re: [PHP-DEV] [RFC] New operator for context-dependent escaping

2016-07-18 Thread Rasmus Schultz
> Registry of functions - is exactly how escaping is performed in Symfony
and Twig.

For one, that does not mean it's a good idea.

For another, the registry in Symfony (at least, I don't know about Twig) is
inside an instance - it's not global state.

Do you get my point that a reference to a closure is state? And if it's
global state, that's extremely bad - the entire PHP community is fighting
like hell to avoid that, with PSR-7 and layers of abstraction on top of,
well, everything, in order to make code testable.

Catering to different skill levels is no excuse.

HTML escaping is, yes, a very pragmatic task - it's also solved already,
with htmlspecialchars() ... the main problem you appear to be solving, is
that htmlspecialchars() is too long and ugly and inconvenient, which, okay,
it is - but adding a global registry for that is overkill, and the whole
problem would go away if you could simply autoload functions:



That's not ugly or inconvenient. The only problem is you can't package your
html() function (and install it with e.g. Composer) because PHP can't
autoload functions.

Functions such as HTML escaping, or any other kind of escaping, do not
belong in a registry - you shouldn't swap out those functions at all, they
need to work precisely as specified, so the caller knows precisely what the
result it, because only the caller can know the context and intent.

I'm not going to go much deeper into it than that, sorry - I don't have
time...


On Sun, Jul 17, 2016 at 4:47 PM, Michael Vostrikov <
michael.vostri...@gmail.com> wrote:

> >
> > All it is, really, is a registry for functions, and syntactic sugar for
> > calling those functions - it's unnecessary, it's more global state you
> have
> > to manage and it's the kind of superficial convenience that will end up
> > breeding more complexity.
> >
>
> Registry of functions - is exactly how escaping is performed in Symfony and
> Twig.
>
> https://github.com/symfony/symfony/blob/f29d46f29b91ea5c30699cf6bdb8e65545d1dd26/src/Symfony/Component/Templating/PhpEngine.php#L421
>
> https://github.com/twigphp/Twig/blob/f0a4fa678465491947554f6687c5fca5e482f8ec/lib/Twig/Extension/Core.php#L1039
>
>
> What's also strange, is the ability to call functions in this registry
> > hinges on syntax. What if I want to call the registered functions from
> > within code?
> > ob_start();
> > ?><* $text *> > $html = ob_get_clean();
> >
>
> Sorry, I don't understand what do you mean in this example. You can call
> your escapers by name or by callable value from array of handlers.
>
> 
> function myHtmlEscaper($str) {
> return htmlspecialchars($str, ENT_QUOTES | ENT_HTML5 |
> ENT_DISALLOWED | ENT_SUBSTITUTE);
> }
>
> PHPEscaper::registerHandler('html', myHtmlEscaper);
> $text = '"Test"';
>
> // 
>
> ob_start();
> ?><* $text *> $html = ob_get_clean();
> var_dump($html);
>
> // string(11) "<* $text *>"
>
> // 
>
> ob_start();
> ?> $html = ob_get_clean();
> var_dump($html);
>
> // string(16) "Test"
>
> // 
>
> $escapers = PHPEscaper::getHandlers();
> $htmlEscaperCallable = $escapers['html'];
> ob_start();
> echo $htmlEscaperCallable($text);
> $html = ob_get_clean();
> var_dump($html);
>
> // string(16) "Test"
>
> ?>
>
>
> > Both variants  and  work good.
> > This is so true - and the whole syntactic convenience line of thinking
> > really should end with that.
> >
>
> Wrong and unsafe variant should not work good.
>
>
> > Also there is a problem with function autoloading.
> > I maintain that this is the real problem, and perhaps the only problem -
> > all this RFC does, is provide a stop-gap solution.
> >
>
> This RFC is not related to function autoloading. It just does not have this
> problem. The code becomes the same as if we will write PHPEscaper::escape()
> manually. In the static calls there is no problem with autoloading.
>
>
> It's somehow easier to choose between two different characters * and =
> > versus electing to call a function or not?
> >
>
> Unsafe variant 'not to call a function' is a short subset of safe variant
> 'call a function'. Safe variant requires additional actions. With new
> operator safe variant is as easy as unsafe.
> And we must not choose, operator  must be used everywhere, except
> 1-2% of cases where we have ready HTML.
> And if we accidentally use it for HTML, this will not be an XSS, it just
> will show double-encoded content, and this will be noticeable.
>
>
> All this RFC changes is the syntax - not the problem.
> >
>
> Ok, what do you think is the problem? As I think, the problem is correct
> HTML escaping and XSS. And it can be solved the same way as in template
> engines. I don't suggest to bring the whole template engine into PHP, only
> escaping mechanism. Function autoloading - is another problem.
>
>
> Addition of a feature like this will affect even those who don't use it
> >
>
> It does not affect any 

  1   2   3   >