Re: [PHP-DEV] [RFC] [VOTE] PHP Attributes

2016-05-15 Thread Larry Garfield

On 05/10/2016 03:48 PM, Benjamin Eberlei wrote:

On Tue, May 10, 2016 at 8:29 PM, Dmitry Stogov  wrote:


Hi internals,


I've started voting on "PHP Attributes" RFC.


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


In my opinion, "PHP Attributes" might be a smart tool for PHP extension,
but it's not going to be the end of the world, if we decided to live with
doc-comments only.


one question, Rasmus Schultz post goes into the similar direction.

Any reason why the annotations are only a numeric list and not key value
pairs? Key-Value would be much more powerful and address a ton of
objections for us (Doctrine).

In the current state it is pretty limited for more complex use-cases. I
don't want to fully embrace the complexities that Larry showed for Drupal
(in my opinion, too much annotations), but without key value pairs we could
only use this when we nested JSON into the attribute value strings for
example, not something I want to mix.


I fully agree that Drupal's annotation use goes over-board at present. 
:-)  I used it as a real-world stress-case.  However, even if we were to 
scale back in Drupal the current Attributes proposal is too low-level to 
be useful.


I do not have voting karma, but I would endorse voting NO on this RFC as is.

--Larry Garfield

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



Re: [PHP-DEV] Assess acceptability of having php-ds into core

2016-05-15 Thread Larry Garfield

On 05/12/2016 08:27 PM, guilhermebla...@gmail.com wrote:

Hi internals,

PHP 7 leverages a lot the performance internally and many PHP applications
in the wild. Much of these improvement came by experimentation through
PHPNG and the usage of efficient data structures internally. This idea of
performance improvements are crucial to handle more requests, reduce server
overload, etc.

However, what lacks in PHP is the exposure of more efficient, use case
specific data structures, that could allow end users to easily improve
performance of their applications, instead of using a general,
multi-purpose data structure that we have as "array".

Based on that (please keep in mind I haven't spoken with library author),
I'd like assess the receptability of incorporating php-ds library into core.

Library author wrote a good (and lengthy) article explaining his motivation
and performance benchmarks around it. Here are the related links:

Article:
https://medium.com/@rtheunissen/efficient-data-structures-for-php-7-9dda7af674cd
Extension: https://github.com/php-ds/extension
Polyfill: https://github.com/php-ds/polyfill
Tests: https://github.com/php-ds/tests
Benchmark: https://github.com/php-ds/benchmarks


Best regards,


I am all for more efficient and performant tools being available 
natively.  However, the php-ds extension in particular, while it sounds 
very nice, is still missing what I believe are key collection-related 
operations, that is, set-level operations.  The equivalents of 
array_map, array_filter, first(callable) (ie, the first item that passes 
a given callable condition), etc. are all extremely powerful 
collection-level, functional operations.  We have array-based versions 
and have for many years, but having them on formal collections or 
objects has always been a sore point, and run into various road blocks 
of "arrays aren't objects", "but then we can't extend the set of 
operations", etc.  The pipe syntax currently being discussed helps some, 
but it's not as clean as doing it natively.


If we're going to improve the quality of our native collection tools, 
then a richer set of operations (for which there is a known list of 
common operations from most functional languages) needs to be part of 
that discussion.


--Larry Garfield

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



Re: [PHP-DEV] [RFC] Pipe Operator

2016-05-15 Thread Larry Garfield

On 05/14/2016 07:42 PM, François Laupretre wrote:

Le 13/05/2016 à 20:16, Sara Golemon a écrit :

for a potential solution to such a long-time issue as argument ordering
sadness, IMHO, it's worth the pain. I am currently doing it and I'll 
send

you the list when it is ready.


Awesome.  Even if not used in this feature, it could potentially be
useful elsewhere.  I hope you put it in a public gist or similar for
posterity.


After a quick check of every functions available in the PHP distrib, 
only 55 functions should insert the lhs in a position different from 0 
(first argument). From these 55 functions, 4 must not be used in a 
pipeline and, for the remaining 51, the lhs must be inserted as 2nd, 
3rd, or 4th argument. The list and positions to use are available at :


http://tekwire.net/joomla/projects/ideas/pipe-operator

So, the logic would be :

- if the function accepts 0 mandatory argument, it cannot be used in a 
pipeline,
- if the function is in the table referenced above, use the position 
from the table,

- else, insert the lhs as 1st arg.

For internal functions, we can easily use some unused part of the 1st 
arginfo element to store the position. The default will remain 0, 
which doesn't require any change in current arginfo declarations. 
We'll just have to define a new ZEND_BEGIN_ARG_INFO_xxx macro with an 
explicit position. This macro will be used for the 55 functions 
requiring a specific non-default position. -1 will be used to mark a 
function as unusable in a pipeline.


Once again, I think that argument ordering is a very important issue 
and, here, we have an unique occasion to solve it for a rather 
moderate price, since every functions have been audited.


Another issue is caused by the sort functions returning the sorted 
array by reference. The problem is the same with or without '$$'. In 
practice, these functions cannot be used in a pipeline. So, either we 
change their behavior to be different when used in a pipeline, which 
is weird but allows an intuitive '|> sort() |>' notation, or we need 
to define a new set of functions returning sorted arrays. None of 
these is perfect but we'll have to propose a solution, as sorting is 
essential when driving an array through a pipeline.


Regards

François


This still sounds awfully complicated to me.  I would far, far prefer 
the $$ syntax to special casing function aliases just to dance around 
it.  If we had a short-function syntax then requiring a piped function 
to have only a single argument would be both reasonable and 
typing-efficient.  Baring that, the $$ syntax seems far nicer than 
alternate versions of functions with implicit arguments but only in 
certain situations.


Side note: Please, people, use the Reply-List function in your email 
clients. I've gotten double-copies of everything in this thread since my 
last email. :-/


Also to Stas: Yes, I meant "continuation" earlier, not "concurrency"; 
brain fart on my part, as the latter clearly makes no sense at all in 
context.  In particular, I'm referring to Continuation-passing style:


https://en.wikipedia.org/wiki/Continuation-passing_style

Again, I think there's a lot of potential to this syntax, especially if 
we can find a way to make it forward-compatible with 
promises/async-await, or whatever we end up with in the async world.  
(Which... I suppose makes continuations a concurrency syntax after all, 
which may be why I brain farted on the C word I meant to type.)


--Larry Garfield

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



Re: [PHP-DEV] [RFC][VOTE] Closure from callable

2016-05-15 Thread Sara Golemon
On Sun, May 15, 2016 at 11:20 AM, Nikita Nefedov  wrote:
> why would you need to support a $this->fieldName case though?
>
Because to not support it would be to deliberately design in a new
flavor of inconsistency into the language. $obj->memb is a property
access in PHP.  Making it suddenly mean "method" is a significant
change (and one which belongs in a major version if at all).

-Sara

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



[PHP-DEV] [VOTE] Forbid dynamic calls to scope introspection functions

2016-05-15 Thread Nikita Popov
Hi internals,

The RFC

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

is now in voting. The vote closes on 2016-05-24 with a required majority of
2/3.

Nikita


Re: [PHP-DEV] [RFC][VOTE] Closure from callable

2016-05-15 Thread Nikita Nefedov

> On 15 May 2016, at 20:29, Dan Ackroyd  wrote:
> 
> Hello,
> 
> I've opened the voting for the Closure from callable RFC -
> https://wiki.php.net/rfc/closurefromcallable
> 
> Just to note, some people I've spoken to have expressed a desire to
> have a more powerful syntax where 'bare' function names are used,
> like:
> 
> callable(someFunctionName)
> callable($this->method)
> 
> I fully agree with those people, however I can't see anyway to do that
> before PHP 8. It would almost certainly need some clean up of the
> allowed syntax to disambiguate what `$this->method` means for:
> 
> class Foo {
>   public $method;
>   public function method() { }
> }
> 
> Leaving that top-level function name available for future versions,
> where we might be able to support it properly, is one of the reasons
> to use the more verbose function name.

Hey Dan,

why would you need to support a $this->fieldName case though? If it's a field 
it probably already contains a closure (or, well, if you need to make a closure 
from arbitrary callable we could have a Closure::fromCallable named ctr). 
Instead of making a function 'callable()', we could make a language construct:

   expr:
   ...
   | T_CALLABLE '(' callable_expr ')'

   callable_expr:
   '$this->' function_name
   | class_name '::' function_name
   | function_name

This would have an advantage of being statically checked (hence easier 
refactoring in IDEs).

I see merging symbol tables as a pretty big of a deal for too much people, this 
thing alone could easily create another case of Python 3 syndrome.



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



[PHP-DEV] [RFC][VOTE] Closure from callable

2016-05-15 Thread Dan Ackroyd
Hello,

I've opened the voting for the Closure from callable RFC -
https://wiki.php.net/rfc/closurefromcallable

Just to note, some people I've spoken to have expressed a desire to
have a more powerful syntax where 'bare' function names are used,
like:

callable(someFunctionName)
callable($this->method)

I fully agree with those people, however I can't see anyway to do that
before PHP 8. It would almost certainly need some clean up of the
allowed syntax to disambiguate what `$this->method` means for:

class Foo {
public $method;
public function method() { }
}

Leaving that top-level function name available for future versions,
where we might be able to support it properly, is one of the reasons
to use the more verbose function name.

cheers
Dan

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



Re: [PHP-DEV] Functorial interfaces

2016-05-15 Thread Niklas Keller
2016-05-15 16:21 GMT+02:00 Rasmus Schultz :

> > As a downside, you can't implement it in a normal class anymore and just
> use
> > an instance of that class.
>
> I see that as a plus, because, as a you said:
>
> > That's why you call it with the method name of the interface
>
> Your logic is circular - you also said:
>
> > As a downside, you can't implement it in a normal class anymore and just
> use
> > an instance of that class.
>
> So you want it both ways, class and callable.
>
> But if I'm not supposed to invoke it as a callable, why implement it
> as a callable in the first place?
>
> In other words, you can't really have both - it doesn't really work: a
> callable can be treated as a class, but a class can't be treated as
> callable. If I have to treat everything as classes anyhow, why not
> just use classes?
>
> The only advantage seems to be shorter syntax than anonymous class
> declarations - the resulting objects have to be treated the same way
> in practice,


>From the RFC:

The anonymous class version:

- must use referencing, or fetch a new Countable object on each iteration,
- is extremely verbose
- must set dependencies in the constructor
- has no support for lexical scope


The functional interface version:

- is sparse
- is easier to reason about
- does not require the use of references
- supports lexical scope
- Functional interface support does not change the definition of an
interface, and only reuse the definition of a Closure.


> e.g. you can't safely treat them as callables. That's
> where the chain falls off for me: you end up with callables, but you
> shouldn't depend on them being callables, so then why make them
> callables in the first place?


Re: [PHP-DEV] Functorial interfaces

2016-05-15 Thread Rasmus Schultz
> As a downside, you can't implement it in a normal class anymore and just use
> an instance of that class.

I see that as a plus, because, as a you said:

> That's why you call it with the method name of the interface

Your logic is circular - you also said:

> As a downside, you can't implement it in a normal class anymore and just use
> an instance of that class.

So you want it both ways, class and callable.

But if I'm not supposed to invoke it as a callable, why implement it
as a callable in the first place?

In other words, you can't really have both - it doesn't really work: a
callable can be treated as a class, but a class can't be treated as
callable. If I have to treat everything as classes anyhow, why not
just use classes?

The only advantage seems to be shorter syntax than anonymous class
declarations - the resulting objects have to be treated the same way
in practice, e.g. you can't safely treat them as callables. That's
where the chain falls off for me: you end up with callables, but you
shouldn't depend on them being callables, so then why make them
callables in the first place?

The net result seems to be syntactic sugar for what is really just
anonymous classes.

I'd like to see an example of how this is really useful in practice -
the example in the RFC seems rather hypothetical, and actually shows
that the same thing is already possible with anonymous classes. Beyond
syntax, where's the real advantage over actual classes or anonymous
classes?


On Sun, May 15, 2016 at 3:28 PM, Niklas Keller  wrote:
> 2016-05-15 12:05 GMT+02:00 Rasmus Schultz :
>>
>> I know you're already voting on this, but I'd like to throw in a
>> couple of late comments.
>>
>> My main problem with this RFC is the use of the interface keyword for
>> something that almost by definition is not an interface.
>>
>> An interface is a set of methods, but an anonymous function is just
>> one function, so it can't possibly implement an interface - this only
>> works because of the single method constraint and some magical mapping
>> of the closure as a method implementing that single-method interface.
>>
>> You can't, for example, add another method to one of these
>> "interfaces", which is problematic - it's inconsistent with what
>> interfaces actually are.
>>
>> In a sense, what you've really done, is you've overloaded the
>> interface concept as a means of shoehorning typedefs into the
>> language.
>>
>> Per the example in the RFC:
>>
>> interface IFoo {
>> public function method() : int;
>> }
>>
>> $cb = function () implements IFoo : int {
>> return 42;
>> };
>>
>> The coupling between $cb and IFoo is explicit - but the coupling
>> between IFoo::method() and the closure is implied; it's something the
>> interpreter, and the person reading the code, has to reason about.
>>
>> The one-method limitation isn't apparent from the "interface"
>> declaration - that is, nothing about the interface declaration implies
>> that it's not actually an interface, e.g. is not a set of methods.
>>
>> On the other hand, I can see the advantages of being able to treat and
>> invoke the closure as if it were an object implementing an interface -
>> it just seems like there's something missing. When a function
>> "implements" an interface, it puts a constraint on that interface,
>> preventing it from taking on another method - it imposes this
>> constraint on the interface from the outside-in, which seems really
>> counter intuitive to me.
>>
>> From the RFC:
>>
>> interface IFoo {
>> public function method1();
>> public function method2();
>> }
>>
>> function () implements IFoo {};
>>
>> This is really surprising if you thought you understood what
>> interfaces are: a set of methods.
>>
>> What suppose I write an interface that has a single method today - and
>> consumers of my library begin to implement this interface using
>> closures in this manner. But then tomorrow, I add another method to my
>> interface? There is suddenly now direct upgrade path, no obvious way
>> to fix the code - they can't simply implement that new method and move
>> on, they now have to start refactoring everything from closures to
>> actual classes.
>
>
> You can just convert the function to an anonymous class. If you add methods
> to an interface,
> that's a BC break for a major version, since it's not compatible anymore,
> everything needs
> an update either way.
>
>>
>> In that sense, this is worse than typedefs - at least typedefs
>> consistently define precisely one function and not a set.
>>
>> Another disconnect from interfaces, is that objects can traditionally
>> implement more than one interface - but an anonymous function can only
>> implement a single interface. It's another deviation from actual
>> interfaces, overloading the interface" keyword - it's inconsistent
>> with interfaces, which is misleading and adds unnecessary learning
>> curve.
>
>
> Literally, an interface is something you 

Re: [PHP-DEV] Functorial interfaces

2016-05-15 Thread Niklas Keller
2016-05-15 12:05 GMT+02:00 Rasmus Schultz :

> I know you're already voting on this, but I'd like to throw in a
> couple of late comments.
>
> My main problem with this RFC is the use of the interface keyword for
> something that almost by definition is not an interface.
>
> An interface is a set of methods, but an anonymous function is just
> one function, so it can't possibly implement an interface - this only
> works because of the single method constraint and some magical mapping
> of the closure as a method implementing that single-method interface.
>
> You can't, for example, add another method to one of these
> "interfaces", which is problematic - it's inconsistent with what
> interfaces actually are.
>
> In a sense, what you've really done, is you've overloaded the
> interface concept as a means of shoehorning typedefs into the
> language.
>
> Per the example in the RFC:
>
> interface IFoo {
> public function method() : int;
> }
>
> $cb = function () implements IFoo : int {
> return 42;
> };
>
> The coupling between $cb and IFoo is explicit - but the coupling
> between IFoo::method() and the closure is implied; it's something the
> interpreter, and the person reading the code, has to reason about.
>
> The one-method limitation isn't apparent from the "interface"
> declaration - that is, nothing about the interface declaration implies
> that it's not actually an interface, e.g. is not a set of methods.
>
> On the other hand, I can see the advantages of being able to treat and
> invoke the closure as if it were an object implementing an interface -
> it just seems like there's something missing. When a function
> "implements" an interface, it puts a constraint on that interface,
> preventing it from taking on another method - it imposes this
> constraint on the interface from the outside-in, which seems really
> counter intuitive to me.
>
> From the RFC:
>
> interface IFoo {
> public function method1();
> public function method2();
> }
>
> function () implements IFoo {};
>
> This is really surprising if you thought you understood what
> interfaces are: a set of methods.
>
> What suppose I write an interface that has a single method today - and
> consumers of my library begin to implement this interface using
> closures in this manner. But then tomorrow, I add another method to my
> interface? There is suddenly now direct upgrade path, no obvious way
> to fix the code - they can't simply implement that new method and move
> on, they now have to start refactoring everything from closures to
> actual classes.
>

You can just convert the function to an anonymous class. If you add methods
to an interface,
that's a BC break for a major version, since it's not compatible anymore,
everything needs
an update either way.


> In that sense, this is worse than typedefs - at least typedefs
> consistently define precisely one function and not a set.
>
> Another disconnect from interfaces, is that objects can traditionally
> implement more than one interface - but an anonymous function can only
> implement a single interface. It's another deviation from actual
> interfaces, overloading the interface" keyword - it's inconsistent
> with interfaces, which is misleading and adds unnecessary learning
> curve.
>

Literally, an interface is something you interact with. It's important for
the consumer
not the class implementing it. If you separate your concerns, you often
have just one interface.


> Another downside of this proposal, is that a single functional
> interface effectively has two names: the type-name and the
> method-name; but both names map to the same thing, the anonymous
> closure. Method-names are necessary in interfaces because they
> identify the individual methods in a set of methods. But functional
> interfaces are not a set of methods. The functional interface
> type-name already designates the type. There is no reason it should
> need to have two names.
>
> How about the following alternative syntax?
>
> callable IFoo = function () : int;
>
> $cb = function () implements IFoo {
> return 42;
> };
>
> With this syntactic sugar, functional interfaces are distinctly
> single-method interfaces - you can't add another method.
>
> You no longer need to come up with two names for one thing.
>
> You don't need to repeat the return-type when implementing it.
>

I like that syntax, but it has its own disadvantages.


> And you don't need to specify that extra method-name when invoking it:
>

As a downside, you can't implement it in a normal class anymore and just use
an instance of that class.


> if ($cb instanceof IFoo) {
> $number = $cb();
> }
>
> It also avoids the following conundrum:
>
> interface Foo {
> public function foo();
> }
>
> interface Bar {
> public function bar();
> }
>
> class Bleet implements Foo, Bar {
> // ...
> }
>
> function fluff(Bleet $bleet) {
> $bleet(); // ERROR!
> }
>
> In this example, the fluff() function thinks it's 

Re: [PHP-DEV] Functorial interfaces

2016-05-15 Thread Rasmus Schultz
I know you're already voting on this, but I'd like to throw in a
couple of late comments.

My main problem with this RFC is the use of the interface keyword for
something that almost by definition is not an interface.

An interface is a set of methods, but an anonymous function is just
one function, so it can't possibly implement an interface - this only
works because of the single method constraint and some magical mapping
of the closure as a method implementing that single-method interface.

You can't, for example, add another method to one of these
"interfaces", which is problematic - it's inconsistent with what
interfaces actually are.

In a sense, what you've really done, is you've overloaded the
interface concept as a means of shoehorning typedefs into the
language.

Per the example in the RFC:

interface IFoo {
public function method() : int;
}

$cb = function () implements IFoo : int {
return 42;
};

The coupling between $cb and IFoo is explicit - but the coupling
between IFoo::method() and the closure is implied; it's something the
interpreter, and the person reading the code, has to reason about.

The one-method limitation isn't apparent from the "interface"
declaration - that is, nothing about the interface declaration implies
that it's not actually an interface, e.g. is not a set of methods.

On the other hand, I can see the advantages of being able to treat and
invoke the closure as if it were an object implementing an interface -
it just seems like there's something missing. When a function
"implements" an interface, it puts a constraint on that interface,
preventing it from taking on another method - it imposes this
constraint on the interface from the outside-in, which seems really
counter intuitive to me.

>From the RFC:

interface IFoo {
public function method1();
public function method2();
}

function () implements IFoo {};

This is really surprising if you thought you understood what
interfaces are: a set of methods.

What suppose I write an interface that has a single method today - and
consumers of my library begin to implement this interface using
closures in this manner. But then tomorrow, I add another method to my
interface? There is suddenly now direct upgrade path, no obvious way
to fix the code - they can't simply implement that new method and move
on, they now have to start refactoring everything from closures to
actual classes.

In that sense, this is worse than typedefs - at least typedefs
consistently define precisely one function and not a set.

Another disconnect from interfaces, is that objects can traditionally
implement more than one interface - but an anonymous function can only
implement a single interface. It's another deviation from actual
interfaces, overloading the interface" keyword - it's inconsistent
with interfaces, which is misleading and adds unnecessary learning
curve.

Another downside of this proposal, is that a single functional
interface effectively has two names: the type-name and the
method-name; but both names map to the same thing, the anonymous
closure. Method-names are necessary in interfaces because they
identify the individual methods in a set of methods. But functional
interfaces are not a set of methods. The functional interface
type-name already designates the type. There is no reason it should
need to have two names.

How about the following alternative syntax?

callable IFoo = function () : int;

$cb = function () implements IFoo {
return 42;
};

With this syntactic sugar, functional interfaces are distinctly
single-method interfaces - you can't add another method.

You no longer need to come up with two names for one thing.

You don't need to repeat the return-type when implementing it.

And you don't need to specify that extra method-name when invoking it:

if ($cb instanceof IFoo) {
$number = $cb();
}

It also avoids the following conundrum:

interface Foo {
public function foo();
}

interface Bar {
public function bar();
}

class Bleet implements Foo, Bar {
// ...
}

function fluff(Bleet $bleet) {
$bleet(); // ERROR!
}

In this example, the fluff() function thinks it's getting an anonymous
function implementing Foo, but that's not the case. But it could be.
You opened that door when you decided to overload interfaces - not
only functions can implement these interfaces, classes can too.

I think this last example demonstrates a huge disconnect - you've
defined something that is apparently both an interface and a typedef
of sorts, but the resulting types are not in fact interchangible. That
is, you can't swap out an anonymous function with a class implementing
that interface, or vice-versa, unless the consumer relies on invoking
the method rather than using the object as a callable. The fact that
it's a callable isn't even a fact you can rely on anymore.

I don't believe this is good. I think that the number of compiler
errors specified in the RFC alone is a flashing red light.

I think that other 

[PHP-DEV] [RFC][Vote] Functional Interfaces

2016-05-15 Thread Joe Watkins
Morning internals,

Functional interfaces has been moved to voting stage, please
participate.

http://wiki.php.net/rfc/functional-interfaces#vote

Cheers
Joe