Hi!
One of the annoying things I've encountered in working with PHP was
dealing with functions having long optional parameter lists, especially
if you need to change only the last one - you have to copy all the
defaults. Full named params implementation would solve it, probably, but
before we have that here's an easier solution for part of the problem:
https://wiki.php.net/rfc/skipparams
Basically, it allows you to do this:
create_query("deleted=0", "name",,, /report_errors/ true);
Implementation of it is here:
https://github.com/smalyshev/php-src/tree/skip_params
All things described in RFC seem to be working, please tell me if I
forgot anything. If it's accepted I'll also add tests, etc. of course.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Stas Malyshev wrote:
Basically, it allows you to do this:
create_query("deleted=0", "name",,, /report_errors/ true);
I'm a huge fan of this idea, for all the reasons listed on the RFC and
one additional one: it brings normal functions in line with the syntax
for list() - We can skip parameters in list() using the same syntax, so
to my eye, this brings consistency.
(Of course, list() is a construct, not a function, but considering how
similar the syntax is, I think this makes sense.)
One of the annoying things I've encountered in working with PHP was
dealing with functions having long optional parameter lists, especially
if you need to change only the last one - you have to copy all the
defaults. Full named params implementation would solve it, probably, but
before we have that here's an easier solution for part of the problem:https://wiki.php.net/rfc/skipparams
Basically, it allows you to do this:
create_query("deleted=0", "name",,, /report_errors/ true);
Pretty cool especially since it avoids the problem when refactoring code
of knowing whether the use of the default param was intentional or just
as a filler to reach a later parameter.
I do have two remarks though:
-
I hope it doesn't mean giving up on named args, because that would
look way cleaner. -
Would it be possible to allow trailing commas in combination to this?
i.e. foo("arg",) would just call foo with "arg" and then the default
value for the second arg if there is one, or just nothing. That would
make multi-line function calls a bit cleaner, and more similar to arrays.
Cheers
--
Jordi Boggiano
@seldaek - http://nelm.io/jordi
https://wiki.php.net/rfc/skipparams
Basically, it allows you to do this:
create_query("deleted=0", "name",,, /report_errors/ true);
+1
- Would it be possible to allow trailing commas in combination to this?
i.e. foo("arg",) would just call foo with "arg" and then the default
value for the second arg if there is one, or just nothing. That would
make multi-line function calls a bit cleaner, and more similar to arrays.
Yet another +1!
--
Regards,
Mike
One of the annoying things I've encountered in working with PHP was
dealing with functions having long optional parameter lists,
especially
if you need to change only the last one - you have to copy all the
defaults. Full named params implementation would solve it, probably,
but
before we have that here's an easier solution for part of the
problem:https://wiki.php.net/rfc/skipparams
Basically, it allows you to do this:
create_query("deleted=0", "name",,, /report_errors/ true);
It might be worth mentioning in the docs edge cases like strtok.
As you all know, I presume, the optional first param restarts parsing
with a new string. When there is only one param, it continues parsing
the previous first argument.
As silly as this may seem to you experts, newbies will probably be
confused by the optional argument syntax versus functions that change
the parameter position...
--
brain cancer update:
http://richardlynch.blogspot.com/search/label/brain%20tumor
Donate:
https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FS9NLTNEEKWBE
Hi,
2012/4/18 Stas Malyshev smalyshev@sugarcrm.com:
Hi!
One of the annoying things I've encountered in working with PHP was
dealing with functions having long optional parameter lists, especially
if you need to change only the last one - you have to copy all the
defaults. Full named params implementation would solve it, probably, but
before we have that here's an easier solution for part of the problem:https://wiki.php.net/rfc/skipparams
Basically, it allows you to do this:
create_query("deleted=0", "name",,, /report_errors/ true);
Implementation of it is here:
https://github.com/smalyshev/php-src/tree/skip_params
All things described in RFC seem to be working, please tell me if I
forgot anything. If it's accepted I'll also add tests, etc. of course.
Introducing "undefined" might be good.
Intention becomes clearer and we may do
if ($var === undefined) {
echo '$var is undefined';
}
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi!
Introducing "undefined" might be good.
Intention becomes clearer and we may doif ($var === undefined) {
echo '$var is undefined';
}
What is undefined and how $var gets assigned it?
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi,
2012/4/18 Stas Malyshev smalyshev@sugarcrm.com:
Hi!
Introducing "undefined" might be good.
Intention becomes clearer and we may doif ($var === undefined) {
echo '$var is undefined';
}What is undefined and how $var gets assigned it?
I'm thinking undefined like JavaScript.
AFAIK, engine does not have undefined state.
It may be too many changes required.
Just skipping would work and I'm not against it.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi,
It's undefined, so it does not have to keep track state ;)
But it may require a lot of changes, so I don't matter much.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
2012/4/18 Yasuo Ohgaki yohgaki@ohgaki.net:
Hi,
2012/4/18 Stas Malyshev smalyshev@sugarcrm.com:
Hi!
Introducing "undefined" might be good.
Intention becomes clearer and we may doif ($var === undefined) {
echo '$var is undefined';
}What is undefined and how $var gets assigned it?
I'm thinking undefined like JavaScript.
AFAIK, engine does not have undefined state.
It may be too many changes required.Just skipping would work and I'm not against it.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi!
I'm thinking undefined like JavaScript.
Well, in PHP null is closest, but a bit different. I.e. in JS undefined
a is an error, but a[0] where a is empty is "undefined". In PHP in both
cases you get null and notice, and in both cases you can use isset/empty
to check for it.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi!
One of the annoying things I've encountered in working with PHP was
dealing with functions having long optional parameter lists, especially
if you need to change only the last one - you have to copy all the
defaults. Full named params implementation would solve it, probably, but
before we have that here's an easier solution for part of the problem:https://wiki.php.net/rfc/skipparams
Basically, it allows you to do this:
create_query("deleted=0", "name",,, /report_errors/ true);
Implementation of it is here:
https://github.com/smalyshev/php-src/tree/skip_params
All things described in RFC seem to be working, please tell me if I
forgot anything. If it's accepted I'll also add tests, etc. of course.
Hi
I like this proposal. One thing pops out at me though.
Since func_num_args()
won't be able to be used to see if an argument is set, could a func_isset_arg() be added? So something like:
if(func_num_args() > 2) $value = func_get_arg(2);
would become:
if(func_isset_arg(2)) $value = func_get_arg(2);
Simon Welsh
Hi,
2012/4/18 Simon J Welsh simon@welsh.co.nz:
Hi!
One of the annoying things I've encountered in working with PHP was
dealing with functions having long optional parameter lists, especially
if you need to change only the last one - you have to copy all the
defaults. Full named params implementation would solve it, probably, but
before we have that here's an easier solution for part of the problem:https://wiki.php.net/rfc/skipparams
Basically, it allows you to do this:
create_query("deleted=0", "name",,, /report_errors/ true);
Implementation of it is here:
https://github.com/smalyshev/php-src/tree/skip_params
All things described in RFC seem to be working, please tell me if I
forgot anything. If it's accepted I'll also add tests, etc. of course.Hi
I like this proposal. One thing pops out at me though.
Since
func_num_args()
won't be able to be used to see if an argument is set, could a func_isset_arg() be added? So something like:
if(func_num_args() > 2) $value = func_get_arg(2);
would become:
if(func_isset_arg(2)) $value = func_get_arg(2);
Good point.
For func_get_arg()
, having "undefined" is mandatory,
otherwise we cannot tell if it is defined or not.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi!
Since
func_num_args()
won't be able to be used to see if an argument is set, could a func_isset_arg() be added? So something like:
if(func_num_args() > 2) $value = func_get_arg(2);
would become:
if(func_isset_arg(2)) $value = func_get_arg(2);
I think it's easier to just do func_get_args()
and check for isset there
:) You usually don't have too many args so getting all of them is not a
big problem.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi,
Hi!
Since
func_num_args()
won't be able to be used to see if an argument is set, could a func_isset_arg() be added? So something like:
if(func_num_args() > 2) $value = func_get_arg(2);
would become:
if(func_isset_arg(2)) $value = func_get_arg(2);I think it's easier to just do
func_get_args()
and check for isset there
:) You usually don't have too many args so getting all of them is not a
big problem.
+1
BTW: the diffs show a lot of WS changes that you should probably fix.
Best,
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227--
--
Etienne Kneuss
http://www.colder.ch
Hi,
Hi!
Since
func_num_args()
won't be able to be used to see if an argument is set, could a func_isset_arg() be added? So something like:
if(func_num_args() > 2) $value = func_get_arg(2);
would become:
if(func_isset_arg(2)) $value = func_get_arg(2);I think it's easier to just do
func_get_args()
and check for isset there
:) You usually don't have too many args so getting all of them is not a
big problem.+1
BTW: the diffs show a lot of WS changes that you should probably fix.
On a side note, one can pass ?w=1 to the github diff, so it will show
up without WS changes:
https://github.com/smalyshev/php-src/commit/0f78493d3e96a627caa8258ee9e618301b6b3511?w=1
Makes is a bit easier to spot the relevant parts.
I'm also +1 on the proposal :)
Nikita
Hi!
BTW: the diffs show a lot of WS changes that you should probably fix.
That's Eclipse, it loves to strip trailing whitespace... Which btw shows
for some reason we have lots of it in our code.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi,
2012/4/18 Stas Malyshev smalyshev@sugarcrm.com:
Hi!
Since
func_num_args()
won't be able to be used to see if an argument is set, could a func_isset_arg() be added? So something like:
if(func_num_args() > 2) $value = func_get_arg(2);
would become:
if(func_isset_arg(2)) $value = func_get_arg(2);I think it's easier to just do
func_get_args()
and check for isset there
:) You usually don't have too many args so getting all of them is not a
big problem.
This works.
I think it's fine with this.
There may be a few codes that have BC issues, but
it's new PHP anyway.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi!
https://wiki.php.net/rfc/skipparams
Basically, it allows you to do this:
create_query("deleted=0", "name",,, /report_errors/ true);
Implementation of it is here:
https://github.com/smalyshev/php-src/tree/skip_params
All things described in RFC seem to be working, please tell me if I
forgot anything. If it's accepted I'll also add tests, etc. of course.
Hate to be contrary, it does raise a few questions.
a) it kind of encourages using long lists of arguments (which is not
normally regarded as good practice)
b) the usual recommendation for solving that issue is to accept an array
(fake named arguments)
c) the current situation would syntax error out on ,, as a function call
argument, which is handy if you accidentally typed ,, twice by accident.
if this changes, not only would you loose this syntax error, but it
would do unpredictable things.
For my 2c, does not look like a very good idea..
Regards
Alan
Hi!
a) it kind of encourages using long lists of arguments (which is not
normally regarded as good practice)
This ship has sailed long ago, these lists are the reality. And
rewriting all the code to change all function calls is in most cases
completely infeasible.
c) the current situation would syntax error out on ,, as a function call
argument, which is handy if you accidentally typed ,, twice by accident.
if this changes, not only would you loose this syntax error, but it
would do unpredictable things.
There are many situations where you could type something by accident and
have it change the meaning of the call. For example, if to type:
if($foo); bar(); then bar() would execute always. This does not prevent
us from using ; as statement separator or from using if's.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
On Tue, Apr 17, 2012 at 6:54 PM, Stas Malyshev smalyshev@sugarcrm.comwrote:
Hi!
One of the annoying things I've encountered in working with PHP was
dealing with functions having long optional parameter lists, especially
if you need to change only the last one - you have to copy all the
defaults. Full named params implementation would solve it, probably, but
before we have that here's an easier solution for part of the problem:https://wiki.php.net/rfc/skipparams
Basically, it allows you to do this:
create_query("deleted=0", "name",,, /report_errors/ true);
Implementation of it is here:
https://github.com/smalyshev/php-src/tree/skip_params
All things described in RFC seem to be working, please tell me if I
forgot anything. If it's accepted I'll also add tests, etc. of course.
Stas, this is fantastic! Not a voter, but I would be very thankful for this
addition to PHP.
Adam
Hi!
My opinion is that solution tries to overcome bad consequences of
legacy code, when it's not feasible to change something without
breakage a lot of code, although the real solution is to refactor
functions with long variable lists (as Uncle Bob says), maybe this
should be noted in documentation of this feature.
Alan nicely highlighted all cons of this feature, but instead of
voting against it I suggest to put that into the docs, so people can
use it wisely and understand consequences.
One question about implementation:
Given we have this function
function create_query($where, $order_by, $join_type='', $execute = false, $report_errors = true) {}
and this statement
On the engine level, it will be implemented by puttingNULL
in the place where the parameter is passed.
what value $join_type will get on this call?
create_query("deleted=0", "name",,, /report_errors/ true);
NULL
or empty string? I.e. will optional parameters always get NULLs
or their default values?
Thanks.
Regards,
Shein Alexey
snip
One question about implementation:
Given we have this functionfunction create_query($where, $order_by, $join_type='', $execute = false, $report_errors = true) {}
and this statement
On the engine level, it will be implemented by puttingNULL
in the place where the parameter is passed.what value $join_type will get on this call?
create_query("deleted=0", "name",,, /report_errors/ true);
NULL
or empty string? I.e. will optional parameters always get NULLs
or their default values?
It needs to be the default values, otherwise it will be a huge WTF for
developers.
With that in mind: +1 if default values are used when skipping
parameters, -1 if NULL
is used when skipping parameters (not that I
have voting power, just showing preferences/support).
Regards
Peter
--
<hype>
WWW: plphp.dk / plind.dk
LinkedIn: plind
BeWelcome/Couchsurfing: Fake51
Twitter: kafe15
</hype
Hi!
NULL
or empty string? I.e. will optional parameters always get NULLs
or their default values?
Their default values. That's the whole point of it - if I wanted just
nulls, I could put nulls in the call, but if I want the actual default,
I'd have to find the definition and copy-paste from there.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
18 апреля 2012 г. 11:40 пользователь Stas Malyshev
smalyshev@sugarcrm.com написал:
Hi!
NULL
or empty string? I.e. will optional parameters always get NULLs
or their default values?Their default values. That's the whole point of it - if I wanted just
nulls, I could put nulls in the call, but if I want the actual default,
I'd have to find the definition and copy-paste from there.
Thank you, that's what I wanted to hear.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
--
Regards,
Shein Alexey
Hi!
My opinion is that solution tries to overcome bad consequences of
legacy code, when it's not feasible to change something without
breakage a lot of code, although the real solution is to refactor
functions with long variable lists (as Uncle Bob says), maybe this
should be noted in documentation of this feature.
I disagree with the suggestion that the "real" solution is to refactor
functions. Is a function with 3 parameters too long?
function foo($val1, $val2 = true, $val3 = false) { /* code */}
If I want to pass in a value to the third argument but keep the default
value for the second argument, I have to look up what the default is and
then paste/type it in as the second argument.
Being able to just call foo($val1 = "something", , $val3 = true) lets me
set a specific value for the 3rd argument without having to do any hunting
down of the 2nd default value or copying/pasting/typing in the argument.
From my perspective, this solution is more about maintaining defaults and
improving developer experience than about problems with legacy code, and it
holds value for any function that has more than one default value.
Adam
I'll keep going offtopic a bit more.
I would rather see named parameters implemented prior to this.
Although maybe not instead, I think both might have their place.
Something like
setcookie( name:'mycookie', value:'abc', secure:true, httponly:true );
is really nice to have. Source code will be much more readable.
I agree with this! But for short array syntax we kept the => as in
$array = ["foo" => "bar"];
Not sure if this was a limitation, lack of that suggestion or a
decision; but the shortest syntax it's still not... (as Yoda would
say!)
$array = ["foo": "bar"]; doesn't look weird to me, plenty readable,
and that's the shortest!
This is getting off-topic, but while we're here, I think:
setcookie($name => 'mycookie', $value => 'abc');
Not sure what the optimal PHP syntax should be for named parameters,
but I think this isn't it.
Back to the topic at hand.
There doesn't need to be a lot of parameters on a function for this to
be useful, even with IDE assistance.
For a proper refactoring, where you'd only needing to change the
function definition. In calls where the optional parameters would call
a 'default', they should in fact be the default. Where as now we'd
have to go through all the function calls for any case where we
statically used the default and change it to the new default...
But I couldn't support the comma train, for the insane «lots of
parameters» case, would hate to read some fn($some,,,, $var,,, $other)
call.
I'd rather reuse a reserved word like 'default' (or even get a shorter one?)
But I couldn't support the comma train, for the insane «lots of
parameters» case, would hate to read some fn($some,,,, $var,,, $other)
call.
I'd rather reuse a reserved word like 'default' (or even get a shorter
one?)
How about "null"? (Tongue firmly in cheek)
You can't do that, NULL
is a perfectly acceptable value to pass into a
function, you wouldn't be able to know when you wanted to pass NULL
or
use the default value, e.g.:
function fn1($a = false, $b = nul, $c = 1)
{
var_dump($a, $b. $c);
}
// your idea
fn1(NULL, NULL, 10), // NULL, NULL, 10
// vs. using a reserved word
fn1(default, default, 10), // FALSE, NULL, 10
Cheers,
But I couldn't support the comma train, for the insane «lots of
parameters» case, would hate to read some fn($some,,,, $var,,, $other)
call.
I'd rather reuse a reserved word like 'default' (or even get a shorter
one?)How about "null"? (Tongue firmly in cheek)
You can't do that,
NULL
is a perfectly acceptable value to pass into a
function, you wouldn't be able to know when you wanted to passNULL
or
use the default value, e.g.:
You totally missed the point: hinting, not-so-subtly, at the
long-established convention to use null as the default value. I guess my
humour doesn't come across so well on the list. Lets get back to
discussing ",,," parameters.
Daniel Macedo wrote:
function fn1($a = false, $b = nul, $c = 1)
{
var_dump($a, $b. $c);
}// your idea
fn1(NULL, NULL, 10), // NULL, NULL, 10// vs. using a reserved word
fn1(default, default, 10), // FALSE, NULL, 10
Of cause one little problem here is if the default gets changed in the 'library'
then every use of 'default' would need to be checked.
Of cause the same problem applies with changing defaults that are used by
leaving out the latter parameters on the list, but this just adds another area
that needs cross checking. Always including the parameters needed is the safe
way in many cases anyway! So leaving them off can be bad practice anyway?
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk//
Firebird - http://www.firebirdsql.org/index.php
I personally would vote for the "default" keyword if I want to skip the
param rather than just doing it with , - the keyword approach is much more
readable and error prone.
I personally would vote for the "default" keyword if I want to skip the
param rather than just doing it with , - the keyword approach is much more
readable and error prone.
I also agree that the "comma-train" (multiple commas without anything
inbetween) might be too confusing and that using a default-keyword
(whatever it might be) might imho be an option.
Regards,
Stefan
I am sorry Lester, but you seem to be getting the "optional parameter"
backwards.
You are supposed to use the optional parameters when it's up to the
library/function definition to determine it's value, not when the
value is what you want for this particular function call!
What you seem to be currently reading from a function definition when
using it is i.e.: "This parameter's default is TRUE? That's what I
need it to be here, skip typing it!"
This is the wrong approach for proper design, and you will have a lot
of headaches when refactoring!
If you use them properly, what you read when using the function call
is "I don't need/want to change the default value for this optional
parameter, use what the library determines!", this is the proper way
to use a function call with optional parameters, that will give you a
LOT less headaches!
The problem with the way things work currently, is that the default
value, is now hard coded into all function calls were you wanted to
use the default, but needed to define a latter optional parameter!
Hence the proper use would be to either use a reserved word, or having
named parameters.
I personally think there's a place for having both.
Daniel Macedo wrote:
function fn1($a = false, $b = nul, $c = 1)
{
var_dump($a, $b. $c);
}// your idea
fn1(NULL, NULL, 10), // NULL, NULL, 10// vs. using a reserved word
fn1(default, default, 10), // FALSE, NULL, 10Of cause one little problem here is if the default gets changed in the
'library' then every use of 'default' would need to be checked.
Of cause the same problem applies with changing defaults that are used by
leaving out the latter parameters on the list, but this just adds another
area that needs cross checking. Always including the parameters needed is
the safe way in many cases anyway! So leaving them off can be bad practice
anyway?--
Lester Caine - G8HFLContact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk//
Firebird - http://www.firebirdsql.org/index.php
Daniel Macedo wrote:
I am sorry Lester, but you seem to be getting the "optional parameter"
backwards.You are supposed to use the optional parameters when it's up to the
library/function definition to determine it's value, not when the
value is what you want for this particular function call!What you seem to be currently reading from a function definition when
using it is i.e.: "This parameter's default is TRUE? That's what I
need it to be here, skip typing it!"
This is the wrong approach for proper design, and you will have a lot
of headaches when refactoring!If you use themproperly, what you read when using the function call
is "I don't need/want to change the default value for this optional
parameter, use what the library determines!", this is the proper way
to use a function call with optional parameters, that will give you a
LOT less headaches!
I'm reading things exactly has they are written ...
If I am USING a later optional parameter, then with well written libraries I
also often need to change the earlier optional ones. Since my IDE provides an
overview of how the defaults have been defined I can check, but I HAVE been
stung by changes of a default value in the library which then messed up
operation requiring the optional parameter to be set. Adding the ability of also
having to check earlier optional parameters just seems adding to the agro
without any real gain! I'm not talking about MY use of this, but is inclusion
without thought in library code.
The problem with the way things work currently, is that the default
value, is nowhard coded into all function calls were you wanted to
use the default, but needed to define a latter optional parameter!Hence the proper use would be to either use a reserved word, or having
named parameters.
I personally think there's a place for having both.
Yet another reason for wanting a LTS version of PHP that we can use without
worrying about all these 'extras'. Named parameters have been discussed in the
past, and not taken forward. If you NEED named parameters, simply use a
parameter hash ... which is the normal practice for 'heavy' parameter passing
anyway.
Similarly if I could trust the library maintainers NOT to change a default, then
'default' might make sense, but to be honest trying to keep libraries working is
as bad nowadays as keeping my own code working as well. I've just finished 3
heavy days making the bulk of the bitweaver code 'strict' safe. Much of the code
still needs extra work, but the bulk of what I USE is now clean. NOW I have to
do the same on the libraries that it uses ... In the absence of a GOOD guide to
'preferred practice' rewriting the bw code to include ALL the public/private
additions will have to wait.
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk//
Firebird - http://www.firebirdsql.org/index.php
Hi!
I'll keep going offtopic a bit more.
I would rather see named parameters implemented prior to this.
I'd rather see named parameters implemented already in 5.0. But somehow
that didn't happen :) It's on my todo list though if nobody beats me to it.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi,
Just a though for named parameter, since it seems
its becoming a relevant topic now.
2012/4/18 Daniel Macedo admacedo@gmail.com:
I'll keep going offtopic a bit more.
I would rather see named parameters implemented prior to this.
Although maybe not instead, I think both might have their place.Something like
setcookie( name:'mycookie', value:'abc', secure:true, httponly:true );
is really nice to have. Source code will be much more readable.
I agree with this! But for short array syntax we kept the => as in
$array = ["foo" => "bar"];
Not sure if this was a limitation, lack of that suggestion or a
decision; but the shortest syntax it's still not... (as Yoda would
say!)$array = ["foo": "bar"]; doesn't look weird to me, plenty readable,
and that's the shortest!
Object can be used as named parameter in JavaScript.
// Define function to take one "argument", which is in fact an object:
function fnParseInt( oArg ){
return parseInt( oArg.number, oArg.radix );
}
// Which you then call like this (pass in an object literal):
fnParseInt( { number : 'afy', radix : 36 } );
If there is a JSON like syntax for PHP objects, named parameter
can be implemented just like this. It would not work for function
that accepts object as first parameter, but who cares?
Pros.
- simple
- everyone are used to JSON and JavaScript now a days
- supporting JSON syntax is convenient for other purpose
- internal functions may support this.
(Single object parameter for this) - coexists func($a,,,,$b)
Cons
- loose type hints
- loose default values for params
- yet another script injection risk if we do "eval($json_data)"
(json_decode() should be used, anyway.)
We may use array to emulate JavaScript, though.
fnParseInt(['number'=>'afy', 'radix'=>36]);
It's many typing compare to other languages, but it works.
If we are going to have array like syntax, we may just
use array.
Anyway, I'm not sure what happened for annotation.
Annotation maybe used as type hints, etc.
Just an idea that I think of now.
There might be many better ideas for named parameter.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
<snip> > > I agree with this! But for short array syntax we kept the => as in > > $array = ["foo" => "bar"]; > > Not sure if this was a limitation, lack of that suggestion or a > > decision; but the shortest syntax it's still not... (as Yoda would > > say!) > > > > $array = ["foo": "bar"]; doesn't look weird to me, plenty readable, > > and that's the shortest! > > Object can be used as named parameter in JavaScript. > > // Define function to take one "argument", which is in fact an object: > function fnParseInt( oArg ){ > return parseInt( oArg.number, oArg.radix ); > } > // Which you then call like this (pass in an object literal): > fnParseInt( { number : 'afy', radix : 36 } ); > > If there is a JSON like syntax for PHP objects, named parameter > can be implemented just like this. It would not work for function > that accepts object as first parameter, but who cares?Just a though for named parameter, since it seems
its becoming a relevant topic now.2012/4/18 Daniel Macedo admacedo@gmail.com :
This is the workaround many of us are already using, though typically
passing an array, not an object. With 5.4, the notation is almost
usable, as you can simply do the square brackets:
fnParseInt([ "number" => "afy", "radix" => 36 ]);
Pros.
- simple
- everyone are used to JSON and JavaScript now a days
- supporting JSON syntax is convenient for other purpose
- internal functions may support this.
(Single object parameter for this)- coexists func($a,,,,$b)
Cons
- loose type hints
- loose default values for params
While the solution is indeed simple, the cons loom very large -- you
end up needing to perform a lot of logic internally in the function in
order to support default values as well as enforce types. That kind of
boilerplate gets very old after a while.
Named parameters would be ideal, but being able to skip parameters will
definitely work in the interim.
--
Matthew Weier O'Phinney
Project Lead | matthew@zend.com
Zend Framework | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
Adam Jon Richardson wrote:
I disagree with the suggestion that the "real" solution is to refactor
functions. Is a function with 3 parameters too long?function foo($val1, $val2 = true, $val3 = false) { /* code */}
If I want to pass in a value to the third argument but keep the default
value for the second argument, I have to look up what the default is and
then paste/type it in as the second argument.
OK we are back in the debate on what needs to be IN the runtime handling ...
Eclipse gives be a pop-up with the parameter set so I know what is expected. I
don't even need to go and 'lookup' anything.
Where the parameter chain is more than a couple of entries, then use a parameter
hash. Always a lot easier anyway when handling SQL type activities as one can
add stuff later and the order is irrelevant anyway.
When one uses the right support tools is this really something to be wasting
even more time on?
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk//
Firebird - http://www.firebirdsql.org/index.php
create_query("deleted=0", "name",,, /report_errors/ true);
I like it. At the risk of bikeshedding, can we have a token rather
than just a series of commas — say reusing the default keyword so it
would look like this instead:
create_query("deleted=0", "name", default, default, /report_errors/ true);
That seems easier to read to my eyes than counting commas.
Thanks,
Adam
On Wed, Apr 18, 2012 at 12:54 AM, Stas Malyshev smalyshev@sugarcrm.comwrote:
Hi!
One of the annoying things I've encountered in working with PHP was
dealing with functions having long optional parameter lists, especially
if you need to change only the last one - you have to copy all the
defaults. Full named params implementation would solve it, probably, but
before we have that here's an easier solution for part of the problem:https://wiki.php.net/rfc/skipparams
Basically, it allows you to do this:
create_query("deleted=0", "name",,, /report_errors/ true);
Implementation of it is here:
https://github.com/smalyshev/php-src/tree/skip_params
All things described in RFC seem to be working, please tell me if I
forgot anything. If it's accepted I'll also add tests, etc. of course.
I would prefer Named parameters, but this is still better than the current
situation.
--
Ferenc Kovács
@Tyr43l - http://tyrael.hu
Hi,
2012/4/18 Ferenc Kovacs tyra3l@gmail.com:
I would prefer Named parameters, but this is still better than the current
situation.
Something like
setcookie( name:'mycookie', value:'abc', secure:true, httponly:true );
is really nice to have. Source code will be much more readable.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Yasuo Ohgaki wrote:
Something like
setcookie( name:'mycookie', value:'abc', secure:true, httponly:true );
is really nice to have. Source code will be much more readable.
This is getting off-topic, but while we're here, I think:
setcookie($name => 'mycookie', $value => 'abc');
...would be better.
--
Ryan McCue
<http://ryanmccue.info/
Hi,
2012/4/18 Ryan McCue lists@rotorised.com:
Yasuo Ohgaki wrote:
Something like
setcookie( name:'mycookie', value:'abc', secure:true, httponly:true );
is really nice to have. Source code will be much more readable.
This is getting off-topic, but while we're here, I think:
setcookie($name => 'mycookie', $value => 'abc');
...would be better.
Real life code would be something like
setcookie($name => $my_cookie_name, $value => $value);
It's confusing.
Off topic anyway.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Am 18.04.2012 09:18, schrieb Ferenc Kovacs:
On Wed, Apr 18, 2012 at 12:54 AM, Stas Malyshev
smalyshev@sugarcrm.comwrote:Hi!
One of the annoying things I've encountered in working with PHP was
dealing with functions having long optional parameter lists,
especially
if you need to change only the last one - you have to copy all the
defaults. Full named params implementation would solve it, probably,
but
before we have that here's an easier solution for part of the
problem:https://wiki.php.net/rfc/skipparams
Basically, it allows you to do this:
create_query("deleted=0", "name",,, /report_errors/ true);
Implementation of it is here:
https://github.com/smalyshev/php-src/tree/skip_params
All things described in RFC seem to be working, please tell me if I
forgot anything. If it's accepted I'll also add tests, etc. of
course.I would prefer Named parameters, but this is still better than the
current
situation.
Every time a new language construct is proposed, the first arguments
against are:
- This is confusing syntax
- It is hard to read
- And so one
Stas, and I think you are one of the core developers which raises his
voice as first, against new language constructs. And now you propose
such a construct. But the best is you show the optimal solution(named
parameters) for this problem in your post, and suggests this proposal as
work around for it. So if this proposal gets implemented and maybe in
the future named parameters gets also implemented. Have we then two
solutions for this problem. Or does we revert your current proposal.
Sorry, its not against you but for me it seems more as a quick shot.
Just my 2 cents
Christian
+1.
I LIKE https://wiki.php.net/rfc/namedparameters , please change OLD decide.
-----邮件原件-----
发件人: Ferenc Kovacs [mailto:tyra3l@gmail.com]
发送时间: 2012年4月18日 15:19
收件人: Stas Malyshev
抄送: PHP Internals
主题: Re: [PHP-DEV] [RFC] skipping optional parameters
On Wed, Apr 18, 2012 at 12:54 AM, Stas Malyshev smalyshev@sugarcrm.comwrote:
Hi!
One of the annoying things I've encountered in working with PHP was
dealing with functions having long optional parameter lists,
especially if you need to change only the last one - you have to copy
all the defaults. Full named params implementation would solve it,
probably, but before we have that here's an easier solution for part of the problem:https://wiki.php.net/rfc/skipparams
Basically, it allows you to do this:
create_query("deleted=0", "name",,, /report_errors/ true);
Implementation of it is here:
https://github.com/smalyshev/php-src/tree/skip_params
All things described in RFC seem to be working, please tell me if I
forgot anything. If it's accepted I'll also add tests, etc. of course.
I would prefer Named parameters, but this is still better than the current situation.
--
Ferenc Kovács
@Tyr43l - http://tyrael.hu
hi Stas,
create_query("deleted=0", "name",,, /report_errors/ true);
I like the concept, a lot :)
Indeed there is the "code written for only this version and above",
from a syntax point of view. But that's something I do not care much
about.
Cheers,
Pierre
@pierrejoye | http://blog.thepimp.net | http://www.libgd.org
One of the annoying things I've encountered in working with PHP was
dealing with functions having long optional parameter lists, especially
if you need to change only the last one - you have to copy all the
defaults. Full named params implementation would solve it, probably, but
before we have that here's an easier solution for part of the problem:https://wiki.php.net/rfc/skipparams
Basically, it allows you to do this:
create_query("deleted=0", "name",,, /report_errors/ true);
I actually had a need for either this or named parameters this past
week, and as such would love to see one or the other in place. While I'd
personally prefer named arguments, this approach would work in most
places I've needed them.
My one comment, which others have raised, is readability of multiple
commas -- TBH, at first glance it has the appearance of a mistake. I
think those suggesting a keyword such as "default" make a good point in
this regard -- it makes it 100% clear that you want the default value
for the argument in that position. This also presents an improvement
over current usage, as you're not hard-coding values in your function
calls themselves -- particularly as the defaults could change in future
refactors.
--
Matthew Weier O'Phinney
Project Lead | matthew@zend.com
Zend Framework | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
Hi!
My one comment, which others have raised, is readability of multiple
commas -- TBH, at first glance it has the appearance of a mistake. I
think those suggesting a keyword such as "default" make a good point in
this regard -- it makes it 100% clear that you want the default value
I wouldn't mind default but that means another keyword which means
another disruption (default would be pretty common method name, etc.)
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi!
My one comment, which others have raised, is readability of multiple
commas -- TBH, at first glance it has the appearance of a mistake. I
think those suggesting a keyword such as "default" make a good point in
this regard -- it makes it 100% clear that you want the default valueI wouldn't mind default but that means another keyword which means
another disruption (default would be pretty common method name, etc.)
"default" is already a reserved keyword. It's used in switch
constructs. So it is safe to use :)
Nikita
Hi!
"default" is already a reserved keyword. It's used in switch
constructs. So it is safe to use :)
Ah, silly me, indeed it is. Then I guess it doesn't hurt to add it as an
option. Will do.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi!
"default" is already a reserved keyword. It's used in switch
constructs. So it is safe to use :)Ah, silly me, indeed it is. Then I guess it doesn't hurt to add it as an
option. Will do.
I can't estimate the amount of breakage, but what about using underscore
(literal _) without quotation marks?
In functional languages it's sometimes the "default match" in pattern
matching, that's at least a loose conversion and I hope not many people
would do
define("_", <whatever>) in their code.
The question now is, if create_query("a", _, _, _, true) really looks
better...
Greetings,
Florian
Hi!
I can't estimate the amount of breakage, but what about using underscore
(literal _) without quotation marks?
This one is taken. See: http://us2.php.net/_
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
2012.04.20. 8:08, "Stas Malyshev" smalyshev@sugarcrm.com ezt írta:
Hi!
I can't estimate the amount of breakage, but what about using underscore
(literal _) without quotation marks?This one is taken. See: http://us2.php.net/_
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227--
Hi,
what is the status of the rfc?
were there any reasons why you didn't called for votes?
Personally I would prefer named parameters also, and I think that we are
too close to the 5.5 feature freeze, but somebody asked why did the
progress stopped and I don't think that there were any showstopper issues.
Hi!
what is the status of the rfc?
were there any reasons why you didn't called for votes?
Personally I would prefer named parameters also, and I think that we are
too close to the 5.5 feature freeze, but somebody asked why did the
progress stopped and I don't think that there were any showstopper issues.
There are some issues with making internal functions compatible with
this and fixing all the tests, and I didn't have enough time to get
through it yet. I hope to get back to it in the near future, but
probably not in time for 5.5 if its schedule stays as it is now. The
concept is basically done but there are all kinds of cleanups to be done
and tests to be fixed and so on and it takes time, unfortunately.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
2012/4/18 Matthew Weier O'Phinney weierophinney@php.net:
My one comment, which others have raised, is readability of multiple
commas -- TBH, at first glance it has the appearance of a mistake. I
think those suggesting a keyword such as "default" make a good point in
this regard -- it makes it 100% clear that you want the default value
for the argument in that position. This also presents an improvement
over current usage, as you're not hard-coding values in your function
calls themselves -- particularly as the defaults could change in future
refactors.
I think we should only support optional parameters using the "default"
keyword as it would probably make things more consistent and less
error prone:
function foo( $bar = "bar", $foo = "foo", $baz = "baz" ) { ... }
foo(,,, "myBaz"); // Thinking changing the value of $baz, but there's
one too much "," and PHP won't complain because of too many arguments
used!
Additionally, we might also want to think about
call_user_func()
/call_user_func_array().
If for the former it could work with:
call_user_func( "foo", , , "myBaz" );
What about the latter?
call_user_func_array( "foo", [2 => "myBaz"] ); // ? Evaluating the
element at index 0 would cause a notice, but would result in a NULL,
so I would say that NULL
is to be used as first parameter.
I have no clue on how to correctly support skipped default values in
that case since there is a big difference in supporting the "default"
keyword inside the method call vs. as an element of an array.
Ideas are welcome!
Last but not least: if skipping optional parameters is implemented,
should we consider the support of default values on the leftmost side
of functions?
function foo( $bar = "bar", $baz ) { ... }
It could make sense that $bar followed by $baz is semantically better
than the opposite for technical reason, and this could be called
using:
foo( default, "baz")
or:
foo(, "baz")
2012/4/18 Matthew Weier O'Phinney weierophinney@php.net :
My one comment, which others have raised, is readability of multiple
commas -- TBH, at first glance it has the appearance of a mistake. I
think those suggesting a keyword such as "default" make a good point in
this regard -- it makes it 100% clear that you want the default value
for the argument in that position. This also presents an improvement
over current usage, as you're not hard-coding values in your function
calls themselves -- particularly as the defaults could change in future
refactors.I think we should only support optional parameters using the "default"
keyword as it would probably make things more consistent and less
error prone:function foo( $bar = "bar", $foo = "foo", $baz = "baz" ) { ... }
foo(,,, "myBaz"); // Thinking changing the value of $baz, but there's
one too much "," and PHP won't complain because of too many arguments
used!Additionally, we might also want to think about
call_user_func()
/call_user_func_array().If for the former it could work with:
call_user_func( "foo", , , "myBaz" );
What about the latter?
call_user_func_array( "foo", [2 => "myBaz"] ); // ? Evaluating the
element at index 0 would cause a notice, but would result in a NULL,
so I would say thatNULL
is to be used as first parameter.
I actually would argue you shouldn't skip parameters when using
call_user_func()
; even with call_user_func_array()
, I'd argue that named
parameters is the only way I'd want to allow skipping parameters.
The reason I argue this is because when dynamically calling a function,
you typically don't actually know exactly what the function/method is --
and thus making any assumptions about the signature other than required
parameters is simply begging for problems.
Last but not least: if skipping optional parameters is implemented,
should we consider the support of default values on the leftmost side
of functions?function foo( $bar = "bar", $baz ) { ... }
It could make sense that $bar followed by $baz is semantically better
than the opposite for technical reason, and this could be called
using:foo( default, "baz")
or:
foo(, "baz")
I'd argue no -- as required arguments should always have precedence over
optional ones in the signature when it comes to position.
--
Matthew Weier O'Phinney
Project Lead | matthew@zend.com
Zend Framework | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
I like the idea. In fact I started to implement it some time ago, but your
patch is really cleaner than mine :)
Otherwise I would prefer to insert the default keyword to make the code
more readable. It might be hard to count when you have something like
function(,,,,true);
P.
Hi!
One of the annoying things I've encountered in working with PHP was
dealing with functions having long optional parameter lists, especially
if you need to change only the last one - you have to copy all the
defaults. Full named params implementation would solve it, probably, but
before we have that here's an easier solution for part of the problem:https://wiki.php.net/rfc/skipparams
Basically, it allows you to do this:
create_query("deleted=0", "name",,, /report_errors/ true);
Implementation of it is here:
https://github.com/smalyshev/php-src/tree/skip_params
All things described in RFC seem to be working, please tell me if I
forgot anything. If it's accepted I'll also add tests, etc. of course.--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
On Wed, 18 Apr 2012 00:54:41 +0200, Stas Malyshev smalyshev@sugarcrm.com
wrote:
[snip]
https://wiki.php.net/rfc/skipparams[snip]
«For internal functions, parameter parser will ignore the NULLs, thus
leaving the defaults supplied by the caller intact. Again, skipping
non-optional parameter is an error.»
This would cause a lot of problems. Basically, all the functions that rely
on ZEND_NUM_ARGS() will have to be changed. You can't tell if a parameter
was passed or not by relying on it.
For instance, if you have ZEND_NUM_ARGS() yielding x, but skipped arg x -
y, now the variable for the argument x - y won't be touched but the
function will think the argument was supplied. Segfaults and unpredictable
behavior due to uninitialized values and other logic errors will follow.
Of course, this because internal functions don't have "default values", at
least not the same way user-land functions do.
This seems a lot of trouble for a feature that, in my opinion, even if it
could be implemented without problems, won't be useful enough to overcome
the strong presumption that exists against new syntax changes. Maybe I'm
lucky, but the problem you're trying to solve is at most an occasional
minor nuisance for me. Plus, this solution encourages bad behavior. If we
want to properly support long argument lists (and I'm not we do), we have
to have named parameters.
--
Gustavo Lopes
Hi!
This would cause a lot of problems. Basically, all the functions that rely
on ZEND_NUM_ARGS() will have to be changed. You can't tell if a parameter
was passed or not by relying on it.
ZEND_NUM_ARGS() would probably work since IIRC it relies on stack size,
not on varargs return. Yes, that means ZEND_NUM_ARGS() and varargs would
return different things, and that means when you manually fetch args
from stack you'd have to check for NULLs - but these cases should be
quite rare and can be handled on case-by-case basis. Most functions
don't - and shouldn't - use manual stack parsing, and for those
everything would work just fine.
the strong presumption that exists against new syntax changes. Maybe I'm
lucky, but the problem you're trying to solve is at most an occasional
minor nuisance for me. Plus, this solution encourages bad behavior. If we
Please look at the RFC, it has links to multiple requests from users for
this feature.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
On Wed, 18 Apr 2012 22:34:23 +0200, Stas Malyshev smalyshev@sugarcrm.com
wrote:
Hi!
This would cause a lot of problems. Basically, all the functions that
rely
on ZEND_NUM_ARGS() will have to be changed. You can't tell if a
parameter
was passed or not by relying on it.ZEND_NUM_ARGS() would probably work since IIRC it relies on stack size,
not on varargs return.
Not sure what you mean here. What is this "varargs return"? As far as I
see, a NULL
pointer is pushed to the stack and ZEND_NUM_ARGS() will return
the size of the stack; in this case, the index of the last argument, not
the number of arguments actually passed. But even if it returned the
number of arguments passed, it would be irrelevant because you would not
know which arguments were passed.
Yes, that means ZEND_NUM_ARGS() and varargs would
return different things, and that means when you manually fetch args
from stack you'd have to check for NULLs - but these cases should be
quite rare and can be handled on case-by-case basis. Most functions
don't - and shouldn't - use manual stack parsing, and for those
everything would work just fine.
This is a straw man argument as I was not addressing manual stack parsing,
but, in any case, I think it reveals even a stronger argument against this
addition. There is no reason to think functions shouldn't do manual
argument parsing. In fact, they do, and there are even many ways to have
them do it -- zpp with Z*/z*/Z+/z+, _zend_get_parameters_array,
zend_get_parameters_ex and more. These are not one or two and they will
stop working,
But to my argument: many functions use ZEND_NUM_ARGS() to determine if an
argument was passed. Sometimes, this is the only way to determine if an
argument was passed -- for instance, if we're using zpp with "l", see
mt_srand()
for an example. For a more drastic example, see the
implementation of PDOStatement::fetchAll().
Now, you may argue that this is a bad practice because you can't pass an
argument with a value with same effect of not passing it, and I would
agree. In fact, I've just gone through a great deal of trouble to avoid
having internal functions with this kind of behavior. See
https://github.com/cataphract/php-src/blob/intl_calendar/ext/intl/calendar/calendar_methods.cpp#L399
-- and guess what -- your feature would break this.
Good or bad, usage of ZEND_NUM_ARGS() is all over the place:
glopes@nebm:~/php/php-src$ git grep -n ZEND_NUM_ARGS | grep -v zend_parse
| grep -v zend_get_parameters | wc -l
364
(I removed its usage in zpp and similar)
the strong presumption that exists against new syntax changes. Maybe I'm
lucky, but the problem you're trying to solve is at most an occasional
minor nuisance for me. Plus, this solution encourages bad behavior. If
wePlease look at the RFC, it has links to multiple requests from users for
this feature.
I don't think this is a strong argument, I could find a number of
proponents for every crazy feature.
--
Gustavo Lopes
Hi!
Not sure what you mean here. What is this "varargs return"? As far as I
zend_parse_parameters has varargs options. See how var_dump is implemented.
the number of arguments actually passed. But even if it returned the
number of arguments passed, it would be irrelevant because you would not
know which arguments were passed.
I would know. Unless you're using "+" in zend_parse_parameters but
actually have positional arguments - so far I know no such functions but
if I discover any I'll see how to handle it.
addition. There is no reason to think functions shouldn't do manual
argument parsing. In fact, they do, and there are even many ways to have
There is. We have API for argument passing, functions should use it. If
you're not using APIs, you'd have to fix your function when something
changes. This is why we have APIs.
them do it -- zpp with Z*/z*/Z+/z+, _zend_get_parameters_array,
zend_get_parameters_ex and more. These are not one or two and they will
stop working,
Z params won't stop working, why should they? They'd just have nulls
there. You'd have to handle these nulls of course.
But to my argument: many functions use ZEND_NUM_ARGS() to determine if an
argument was passed. Sometimes, this is the only way to determine if an
argument was passed -- for instance, if we're using zpp with "l", see
mt_srand()
for an example. For a more drastic example, see the
implementation of PDOStatement::fetchAll().
Passing default to mt_srand makes little sense since mt_srand doesn't
have default documented. But we can define it as being 0. Of course,
mt_srand(default) will be different from mt_srand()
then, but so what?
It doesn't break anything.
For fetchAll() NULL
there might be indeed unexpected - so we may think
about either fixing such cases or letting zend_parse_parameters know if
this parameter can handle default (most can) or it does some fancy stuff
with argument dependencies.
Now, you may argue that this is a bad practice because you can't pass an
argument with a value with same effect of not passing it, and I would
agree. In fact, I've just gone through a great deal of trouble to avoid
having internal functions with this kind of behavior. See
https://github.com/cataphract/php-src/blob/intl_calendar/ext/intl/calendar/calendar_methods.cpp#L399
-- and guess what -- your feature would break this.
I don't think it will break that. You may have to do a bit more work to
do it, but it can be done. Though frankly I have no idea what that code
is supposed to do and suspect it is not really a good API if it requires
this level of variation in one function. It basically doing all
parameters handling by itself instead of using system API and this is
usually a bad sign. With or without this feature, I would seriously
consider redesigning it and making it simpler. But again, I have no clue
what this function is supposed to do. Which, BTW, is pretty bad since
apparently it is committed to main code base without having any
comments, prototypes, RFCs, documentation or anything - how one would be
supposed to make any use of it?
Good or bad, usage of ZEND_NUM_ARGS() is all over the place:
glopes@nebm:~/php/php-src$ git grep -n ZEND_NUM_ARGS | grep -v zend_parse
| grep -v zend_get_parameters | wc -l
364
Yeah, I've fallen into this trap too initially. Most of those are
multiline calls to zend_parse_parameters and checks that are completely
harmless. There will be some cases where they aren't - like when default
parameters depend on each other like in fetchAll() - but those can be
handled. Functions like yours above are extremely rare and should be.
And if we ever get names params you'd have to rewrite it anyway so I'd
seriously consider starting to think how it would work with it then. I'd
go with "+" or "*" but that's just a guess.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
On Wed, 18 Apr 2012 23:35:37 +0200, Stas Malyshev smalyshev@sugarcrm.com
wrote:
Before addressing the points individually, I have to reiterate that
internal functions have no concept of default values. I think this
proposal or a named arguments proposal is really ill-advised without
introducing proper default values for internal functions. Then the engine
could pass those default values on the stack and we would have none of
these problems.
Instead, we have lots of functions that will not only break (see below for
a definition of "break"), but break subtly (e.g. uninitialized values) and
only under very particular conditions (using this new feature). Plus, they
increase the complexity of doing argument parsing (surely no one will
forget checking for NULLs). All the functions that use ZEND_NUM_ARGS()
have to be reviewed and the PHP core is just the tip of the iceberg.
the number of arguments actually passed. But even if it returned the
number of arguments passed, it would be irrelevant because you would not
know which arguments were passed.I would know. Unless you're using "+" in zend_parse_parameters but
actually have positional arguments - so far I know no such functions but
if I discover any I'll see how to handle it.
I was talking about ZEND_NUM_ARGS(). My point is that ZEND_NUM_ARGS() now
gives near-0 useful information. Yes, you can know which arguments were
passed through other means, but not via ZEND_NUM_ARGS(), which what many
functions are currently using.
Z params won't stop working, why should they? They'd just have nulls
there. You'd have to handle these nulls of course.
When I say this "breaks" current functions, I don't mean they will never
work again. I mean that, due to different semantics in argument passing,
they will have to be changed. I'm assuming even the though cases like
PDOStatement::fetchAll() can be fixed.
Passing default to mt_srand makes little sense since mt_srand doesn't
have default documented. But we can define it as being 0. Of course,
mt_srand(default) will be different frommt_srand()
then, but so what?
It doesn't break anything.
mt_srand()
was a bad example. But let's supposed it didn't initialize
seed. It would be perfectly correct under current semantics, but as far as
I understand under the patch mt_srand(default) would result in
uninitialized data being used.
https://github.com/cataphract/php-src/blob/intl_calendar/ext/intl/calendar/calendar_methods.cpp#L399
-- and guess what -- your feature would break this.I don't think it will break that. You may have to do a bit more work to
do it, but it can be done. Though frankly I have no idea what that code
is supposed to do and suspect it is not really a good API if it requires
this level of variation in one function. It basically doing all
parameters handling by itself instead of using system API and this is
usually a bad sign.
All it does is check for (PHP) NULLs before using zpp with "l", because
"l" would convert the NULL
to 0 and I want to distinguish the two cases,
so that I can use NULL
to the same effect of not passing the argument.
This was actually discussed in a pull request a few weeks ago.
Good or bad, usage of ZEND_NUM_ARGS() is all over the place:
glopes@nebm:~/php/php-src$ git grep -n ZEND_NUM_ARGS | grep -v
zend_parse
| grep -v zend_get_parameters | wc -l
364Yeah, I've fallen into this trap too initially. Most of those are
multiline calls to zend_parse_parameters and checks that are completely
harmless.
Quickly skimming the output with shows that in some cases it's multiline
calls, but those are in a clear minority (most are in if/switch
statements). And remember, this is just PHP core, a small fraction of all
extensions.
--
Gustavo Lopes
Hi!
Before addressing the points individually, I have to reiterate that
internal functions have no concept of default values. I think this
I disagree. Most of them certainly do, for example, look at strpos
documentation:
int strpos ( string $haystack , mixed $needle [, int $offset = 0 ] )
$offset is documented as having default of 0. Right now it is
implemented in ad-hoc manner - i.e. you set up the value, but you don't
actually declare it anywhere as some special "default value". But it is
certainly there and for the user it is certainly a default as any other.
We didn't do the best job documenting all these, unfortunately (see
below) but in almost all cases they are there.
Instead, we have lots of functions that will not only break (see below for
a definition of "break"), but break subtly (e.g. uninitialized values) and
Any function that passes uninitialized value to optional argument has a
bug and needs to be fixed.
only under very particular conditions (using this new feature). Plus, they
increase the complexity of doing argument parsing (surely no one will
forget checking for NULLs). All the functions that use ZEND_NUM_ARGS()
have to be reviewed and the PHP core is just the tip of the iceberg.
For 99.9% of the functions there's no increase of complexity since they
already do the right thing. As for the matter of checking for NULL
being
too complex - this is the absolutely basic thing you always do in C,
check your pointers, if you write engine code it can't be too complex
for you.
I was talking about ZEND_NUM_ARGS(). My point is that ZEND_NUM_ARGS() now
gives near-0 useful information. Yes, you can know which arguments were
passed through other means, but not via ZEND_NUM_ARGS(), which what many
functions are currently using.
This is not true. It gives the same information as before, and it is
very useful. The only case where you'd have to take some extra case is
where you do not use recommended APIs but try to fetch arguments from
stack manually or when you have complex dependencies between parameters.
Then you'd have to check for NULLs and decide if you are ready to accept
parameters after that. Not rocket science by any measure.
When I say this "breaks" current functions, I don't mean they will never
work again. I mean that, due to different semantics in argument passing,
they will have to be changed. I'm assuming even the though cases like
PDOStatement::fetchAll() can be fixed.
Yes, some functions with extremely complex corner cases of parameter
parsing will have to be slightly changed. I'll think how to make this
change easier. Of course, for this functions notion of default
parameters won't work - we may even introduce some API to tell
zend_parse_parameters about it. But for many other functions it may work
just fine. For example, in the same PDO you have:
bool PDOStatement::bindColumn ( mixed $column , mixed &$param [, int
$type [, int $maxlen [, mixed $driverdata ]]] )
Now, what you do if you want to supply $driverdata but don't care about
max length? We have two problems here:
- Defaults are not documented, so you have zero idea how to get default
behavior without looking into C code. - Defaults could change and you'd have to change your code.
Skipping parameters would work here just fine and will use the same
defaults the code uses, with zero pain to the user.
mt_srand()
was a bad example. But let's supposed it didn't initialize
seed. It would be perfectly correct under current semantics, but as far as
I understand under the patch mt_srand(default) would result in
uninitialized data being used.
If it didn't initialize seed, it would be a bug which even now needs to
be fixed. You're not supposed to pass uninitialized values for default
args into zend_parse_parameters, if you code does that, please fix it ASAP.
All it does is check for (PHP) NULLs before using zpp with "l", because
"l" would convert theNULL
to 0 and I want to distinguish the two cases,
so that I can useNULL
to the same effect of not passing the argument.
This was actually discussed in a pull request a few weeks ago.
This seems to be a very unusual special case then, which has very little
to do with topic at hand. Probably unique case in our code. Maybe we
need to change zend_parse_parameters API or your function API or do some
other good solution for it, but it's offtopic for now. Feel free to open
a new thread on that, but for purposes of this one the conclusion is -
yes, if you ignore system APIs then there's some work to be done there.
I'll scan the code for such functions and see how to fix it best, thanks
for bringing this issue to my attention. I do not see however that it
somehow invalidates the concept, as 99% of the functions do not do that
and you're not supposed to do that except in very special circumstances.
Quickly skimming the output with shows that in some cases it's multiline
calls, but those are in a clear minority (most are in if/switch
statements). And remember, this is just PHP core, a small fraction of all
extensions.
Again, unless you ignore zend_parse_parameters API and cook your own
parsing, your extension is just fine, which will cover about 99% of
them. For the rest, I'll look for a solution.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227