Re: [PHP-DEV] [RFC]

This is only part of a thread. view whole thread
  108549
February 13, 2020 18:48 larry@garfieldtech.com ("Larry Garfield")
On Thu, Feb 13, 2020, at 12:19 PM, Mike Schinkel wrote:
> > On Feb 13, 2020, at 12:26 PM, Rowan Tommins collins@gmail.com> wrote: > > Right, I'm with you now. However, I think the answer people are suggesting > > to "how do we get the name string?" is "why do we need to?" > > 1. Say I want to provide users with the ability to build queries and > use functions where I want to provide the names of the functions to the > users: > > $qt = QueryTool(); > $qt->addFunction(substr::function); > $qt->addFunction(add_product::function); > $qt->showUI(); > > 2. Say I want to serialize any configuration that uses functions. You > can't serialize closures but you can serialize function names to a > database or JSON. > > 3. You cannot use a closure as an array index so if you want to use the > function name as an array key to associate additional information to > the use with the function, such as: > > $qt = QueryTool(); > $qt->addFunction(substr::function, array( > new FuncParam( 'string', 'string' ), > new FuncParam( 'int', 'start', QueryTool::Optional ), > new FuncParam( 'int', 'length', QueryTool::Optional ) > )); > $qt->addFunction(add_product::function, array( > new FuncParam( 'string', 'product_id' ), > new FuncParam( 'float', 'price' ) > ));
Those are valid examples. I suppose along similar lines would be tooling that uses a builder to generate compiled code. (Eg, if $qt were used to then generate an optimized function in a class on disk.) Flipside: In those cases we really should standardize static methods better than with arrays, yet none of these address (nor can they) instance methods.
> 4. Being able to compose quality error and warning message that include > function names. > > > Or as Chase Peeler more eloquently put it: > > > >> Can anyone think of a use-case where you would want a string name of a > >> function and a callable would not be acceptable, besides possibly debugging > >> code that said 'echo "I'm calling ".myfunction::function;'? Everything that > >> I can think of that accepts a function name, also accepts a callable (e.g. > >> array_map), but I could be forgetting something. > > Eloquently maybe, but of limited vision. > > > > There's a Venn diagram, essentially, of: > > a) use cases where a Closure would be useful, but a string wouldn't > > b) use cases where a string would be useful, but a Closure wouldn't > > c) use cases where either a string or a Closure would be useful > > > > If (and it's a genuine open question) all the use cases fall into > > categories (a) and (c), we can make the syntax for closures simpler by > > skipping the "get name" step and making foo::fn return a closure straight > > away. > > > > So the question is, are there use cases that fall into category (b)? > > Yes. Definitely.
I agree, the above examples demonstrate valid use cases for (b).
> But since I seem to be in the minority of caring about the name, let me > propose the following which was influenced by Larry Garfield's most > recent post. Since it seems that people want the convenience of a > short notation to get a closure, how about this: > > function foo{} > > foo::function — Returns name of function > foo::fn — Returns closure for function > > Since using `fn` creates anonymous function closures it kinda makes > sense that `::fn` would return a closure. > > -Mike
thinking-face-emoji.gif. I could be convinced of that. It seems like "both" is a possible solution, but my concern would be someone using one of them in a case where either works, inadvertently, when the callee is expecting just one. Eg, getting into the habit of using foo::fn, and then using it on a builder routine that chokes "later" when it tries to serialize something. --Larry Garfield
  108550
February 13, 2020 20:12 mike@newclarity.net (Mike Schinkel)
> On Feb 13, 2020, at 1:48 PM, Larry Garfield <larry@garfieldtech.com> wrote: >> But since I seem to be in the minority of caring about the name, let me >> propose the following which was influenced by Larry Garfield's most >> recent post. Since it seems that people want the convenience of a >> short notation to get a closure, how about this: >> >> function foo{} >> >> foo::function — Returns name of function >> foo::fn — Returns closure for function >> >> Since using `fn` creates anonymous function closures it kinda makes >> sense that `::fn` would return a closure. >> >> -Mike > > thinking-face-emoji.gif. I could be convinced of that. It seems like "both" is a possible solution, but my concern would be someone using one of them in a case where either works, inadvertently, when the callee is expecting just one. Eg, getting into the habit of using foo::fn, and then using it on a builder routine that chokes "later" when it tries to serialize something.
True. But it would be a really high bar to say we can only add new features if we can completely protect the developer from themselves. At some point we have to assume programmers are adults, or at least can take responsibility for learning how the language works. -Mike P.S. OTOH, if the routine that requires ::function and not ::fn were to type hint the parameter, it would choke with an applicable error message.
  108552
February 13, 2020 21:55 larry@garfieldtech.com ("Larry Garfield")
On Thu, Feb 13, 2020, at 2:12 PM, Mike Schinkel wrote:
> > On Feb 13, 2020, at 1:48 PM, Larry Garfield <larry@garfieldtech.com> wrote: > >> But since I seem to be in the minority of caring about the name, let me > >> propose the following which was influenced by Larry Garfield's most > >> recent post. Since it seems that people want the convenience of a > >> short notation to get a closure, how about this: > >> > >> function foo{} > >> > >> foo::function — Returns name of function > >> foo::fn — Returns closure for function > >> > >> Since using `fn` creates anonymous function closures it kinda makes > >> sense that `::fn` would return a closure. > >> > >> -Mike > > > > thinking-face-emoji.gif. I could be convinced of that. It seems like "both" is a possible solution, but my concern would be someone using one of them in a case where either works, inadvertently, when the callee is expecting just one. Eg, getting into the habit of using foo::fn, and then using it on a builder routine that chokes "later" when it tries to serialize something. > > True. > > But it would be a really high bar to say we can only add new features > if we can completely protect the developer from themselves. At some > point we have to assume programmers are adults, or at least can take > responsibility for learning how the language works.
Strawman argument. Nothing can "completely" protect developers from themselves; not even Rust. :-) But features should still be designed in such a way as to be hard to screw up. Not impossible, hard. The question I pose is whether "both" would be "hard enough" to get wrong that it's not going to cause more confusion than it solves. I don't know the answer to that question. --Larry Garfield