RFC Posted for str_begins and str_ends functions

php.internals

Unnamed Person

10 years ago
Hello, I recently emailed the group about submitting an RFC for str_begins() and str_ends() functions. The RFC has now been officially submitted and is viewable at: https://wiki.php.net/rfc/add_str_begin_and_end_functions The github PR may be found at: https://github.com/php/php-src/pull/2049 Hope to be hearing about this, Will

Sara Golemon

10 years ago
On Mon, Aug 1, 2016 at 3:52 PM, <will@wkhudgins.info> wrote:
> I recently emailed the group about submitting an RFC for str_begins() and > str_ends() functions. The RFC has now been officially submitted and is > viewable at: > > https://wiki.php.net/rfc/add_str_begin_and_end_functions >
Feeling "meh" on it (neither for nor against), but I would consider consistency with other str*() functions by making case-insensitivity live in separate functions rather than as a parameter. e.g. str_begins(), str_ibegins(), str_ends(), end_iends() -Sara

Yasuo Ohgaki

10 years ago
On Tue, Aug 2, 2016 at 7:56 AM, Sara Golemon <pollita@php.net> wrote:
> On Mon, Aug 1, 2016 at 3:52 PM, <will@wkhudgins.info> wrote: >> I recently emailed the group about submitting an RFC for str_begins() and >> str_ends() functions. The RFC has now been officially submitted and is >> viewable at: >> >> https://wiki.php.net/rfc/add_str_begin_and_end_functions >> > Feeling "meh" on it (neither for nor against), but I would consider > consistency with other str*() functions by making case-insensitivity > live in separate functions rather than as a parameter. e.g. > str_begins(), str_ibegins(), str_ends(), end_iends()
+1 for having functions for case insensitivity. I'm not sure if we should have "s". i.e. str_begin"s". Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

David Rodrigues

10 years ago
Sara Golemon wrote:
> Feeling "meh" on it (neither for nor against), but I would consider > consistency with other str*() functions by making case-insensitivity > live in separate functions rather than as a parameter. e.g. > str_begins(), str_ibegins(), str_ends(), end_iends()
I guess that "i" isn't appliable when it have slashes. In this case, functions should be: strbegins, stribegins, strends, striends. In all case, I think that is better a third parameter and keep underlined. Yasuo Ohgaki wrote:
> +1 for having functions for case insensitivity. > I'm not sure if we should have "s". i.e. str_begin"s".
I think that "s" is good here. Sounds better for me, but I don't know if it is right in english. In JS, for instance, we have startsWith. It have a "s" too. 2016-08-01 21:06 GMT-03:00 Yasuo Ohgaki <yohgaki@ohgaki.net>:
> On Tue, Aug 2, 2016 at 7:56 AM, Sara Golemon <pollita@php.net> wrote: >> On Mon, Aug 1, 2016 at 3:52 PM, <will@wkhudgins.info> wrote: >>> I recently emailed the group about submitting an RFC for str_begins() and >>> str_ends() functions. The RFC has now been officially submitted and is >>> viewable at: >>> >>> https://wiki.php.net/rfc/add_str_begin_and_end_functions >>> >> Feeling "meh" on it (neither for nor against), but I would consider >> consistency with other str*() functions by making case-insensitivity >> live in separate functions rather than as a parameter. e.g. >> str_begins(), str_ibegins(), str_ends(), end_iends() > > +1 for having functions for case insensitivity. > I'm not sure if we should have "s". i.e. str_begin"s". > > Regards, > > -- > Yasuo Ohgaki > yohgaki@ohgaki.net > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php >
-- David Rodrigues

Yasuo Ohgaki

10 years ago
Hi David, On Tue, Aug 2, 2016 at 10:36 AM, David Rodrigues <david.proweb@gmail.com> wrote:
> Sara Golemon wrote: >> Feeling "meh" on it (neither for nor against), but I would consider >> consistency with other str*() functions by making case-insensitivity >> live in separate functions rather than as a parameter. e.g. >> str_begins(), str_ibegins(), str_ends(), end_iends() > > I guess that "i" isn't appliable when it have slashes. > In this case, functions should be: strbegins, stribegins, strends, striends. > In all case, I think that is better a third parameter and keep underlined.
This is difficult issue. String function names are inconsistent currently. It is better to stick to CODING_STANDARDS naming convention for new function names. Therefore, new string functions are better to be named str_*() unless they are too strange. e.g. http://php.net/manual/en/function.str-replace.php http://php.net/manual/en/function.str-ireplace.php I would like to fix function name inconsistencies by having aliases in near future. https://wiki.php.net/rfc/consistent_function_names It might be okay to have "s" in function names, but if we want to be consistent, str_replace -> str_replaces str_ireplace -> str_ireplaces IMO, following names are better for consistency. str_begin str_ibegin str_end str_iend In addition, str_replace() has seach_value at first, so signature might be boolean str_begin(string $search_value, string $str, [boolean $case_sensitive = true]) boolean str_end(string $search_value, string $str, string $search_value [boolean $case_sensitive = true]) However, strstr() (and other str functions without "_". e.g. strpos/stripos/strrpos/strripos) has search_value as the 2nd parameter. If we follow this format, current signature is fine. It may be better sort out and fix consistency issues first, then add new functions. Otherwise, we may introduce more consistency issues. Regards, BTW, having "i" is more readable. str_ibegin("searchthis", $str); is more readable than str_begin("seachthis", $str, TRUE); as programmer does not have to know that's the TRUE means. It's small thing, but small things add up.
-- Yasuo Ohgaki yohgaki@ohgaki.net

Rowan Collins

10 years ago
On 02/08/2016 23:44, Yasuo Ohgaki wrote:
> It might be okay to have "s" in function names, but if we want to be > consistent, > > str_replace -> str_replaces > str_ireplace -> str_ireplaces > > IMO, following names are better for consistency. > > str_begin > str_ibegin > str_end > str_iend
I think those names mean something different: "str_begin" sounds like an imperative "make this string begin with X"; "str_begins" is more of an assertion "the string begins with X". Ruby would spell it with a ? at the end. It's also the same form, grammatically, as the common "isFoo". Note that this logic holds for "str_replace", which *is* an imperative - you are not saying "tell me if X replaces Y", you are saying "please replace X with Y". Regards,
-- Rowan Collins [IMSoP]

Unnamed Person

10 years ago
On 2016-08-02 18:44, Yasuo Ohgaki wrote:
> Hi David, > > On Tue, Aug 2, 2016 at 10:36 AM, David Rodrigues > <david.proweb@gmail.com> wrote: >> Sara Golemon wrote: >>> Feeling "meh" on it (neither for nor against), but I would consider >>> consistency with other str*() functions by making case-insensitivity >>> live in separate functions rather than as a parameter. e.g. >>> str_begins(), str_ibegins(), str_ends(), end_iends() >> >> I guess that "i" isn't appliable when it have slashes. >> In this case, functions should be: strbegins, stribegins, strends, >> striends. >> In all case, I think that is better a third parameter and keep >> underlined. > > This is difficult issue. > String function names are inconsistent currently. > It is better to stick to CODING_STANDARDS naming convention for new > function names. Therefore, new string functions are better to be named > str_*() unless they are too strange. > > e.g. > http://php.net/manual/en/function.str-replace.php > http://php.net/manual/en/function.str-ireplace.php > > I would like to fix function name inconsistencies by having aliases in > near future. > https://wiki.php.net/rfc/consistent_function_names > > It might be okay to have "s" in function names, but if we want to be > consistent, > > str_replace -> str_replaces > str_ireplace -> str_ireplaces > > IMO, following names are better for consistency. > > str_begin > str_ibegin > str_end > str_iend > > In addition, str_replace() has seach_value at first, so signature might > be > > boolean str_begin(string $search_value, string $str, [boolean > $case_sensitive = true]) > boolean str_end(string $search_value, string $str, string > $search_value [boolean $case_sensitive = true]) > > However, strstr() (and other str functions without "_". e.g. > strpos/stripos/strrpos/strripos) has search_value as the 2nd > parameter. If we follow this format, current signature is fine. > > It may be better sort out and fix consistency issues first, then add > new functions. Otherwise, we may introduce more consistency issues. > > Regards, > > BTW, having "i" is more readable. > > str_ibegin("searchthis", $str); > is more readable than > str_begin("seachthis", $str, TRUE); > as programmer does not have to know that's the TRUE means. > It's small thing, but small things add up. > > -- > Yasuo Ohgaki > yohgaki@ohgaki.net
Everyone has raised important considerations. For me, the most important thing is maintaining consistency with the existing PHP string library. I do not want these functions to feel "tacked" on, as if they were haphazardly added to PHP. If these functions are added to the language, it should feel as if they have always been a part of the language (even if they haven't been). This consistency is important in order to ensure these functions ADD to PHP instead of just cluttering it up. Having separate functions for case sensitivity makes sense, that is much more consistent with the existing string library. I think the proposal should be amended to separate those two functionalities. I think like having an "s" at the end of the function names reads better, but omitting the "s" fits better with the existing function names and does not read bad. Therefore, I am in favor of dropping the "s". As far as str_begin vs strbegin, I think str_begin is more readable. Therefore, I think it would be better to implement: boolean str_begin(string $search_value, string $str) boolean str_ibegin(string $search_value, string $str) boolean str_end(string $search_value, string $str) boolean str_iend(string $search_value, string $str) This is much more consistent with the existing string library. Regards, Will

Yasuo Ohgaki

10 years ago
On Wed, Aug 3, 2016 at 7:44 AM, Yasuo Ohgaki <yohgaki@ohgaki.net> wrote:
> as programmer does not have to know that's the TRUE means.
s/that's/what's/ I shouldn't write mails while writing code :(
-- Yasuo Ohgaki yohgaki@ohgaki.net

Stas Malyshev

10 years ago
Hi!
> I guess that "i" isn't appliable when it have slashes. > In this case, functions should be: strbegins, stribegins, strends, striends. > In all case, I think that is better a third parameter and keep underlined.
Please, not stribegins. We have enough functions with weird names :) I am ambivalent of the question whether to have additional argument or two functions, I guess with a slight preference for argument.
-- Stas Malyshev smalyshev@gmail.com

Unnamed Person

10 years ago
I've updated the RFC to reflect the discussion here and on github. You may see it at https://wiki.php.net/rfc/add_str_begin_and_end_functions . You can see the github PR at https://github.com/php/php-src/pull/2049 . The motivation for these changes was to maximize consistency between the proposed functions and existing PHP string functions. The goal is to make these functions feel natural and add functionality to the language without cluttering it up. Thanks, Will

Bishop Bettini

10 years ago
On Fri, Aug 12, 2016 at 8:37 PM, <will@wkhudgins.info> wrote:
> I've updated the RFC to reflect the discussion here and on github. You may > see it at > https://wiki.php.net/rfc/add_str_begin_and_end_functions . You can see > the github PR at https://github.com/php/php-src/pull/2049 . > > The motivation for these changes was to maximize consistency between the > proposed functions and existing PHP string functions. The goal is to make > these functions feel natural and add functionality to the language without > cluttering it up. >
Generally, +1. A few thoughts. First, the RFC refers to these working on "characters". I assume you mean ASCII characters and these actually work strictly on bytes. Working on "characters" would be more in-line for a multi-byte extension. Would you please clarify this point? Second, and related to the multi-byte issue: do the case insensitive versions honor case-folding in a multi-byte fashion? Either way, it's probably a good idea to separate the vote between the sensitive and insensitive versions because this is fundamentally a different, and perhaps more contentious, question. Third, perhaps these functions could provide more information than just yes/no. Return boolean TRUE if and only if the needle completely begins/ends the haystack, otherwise return INT representing the length in common. Yes, that'll probably be a trap for new developers who don't honor ===, but that could be illuminated in docs. Formally: boolean|int str_begin(string $needle, string $haystack) boolean|int str_end(string $needle, string $haystack) For example: str_begin('http://', 'http://example.com') === true str_begin('http://', 'https://example.com') === 4 Finally, since the RFC will fuel the final documentation, it might be a good idea to use needle/haystack terminology in the function signatures for some kind of consistency.

Lester Caine

10 years ago
On 04/08/16 06:50, Stanislav Malyshev wrote:
>> I guess that "i" isn't appliable when it have slashes. >> > In this case, functions should be: strbegins, stribegins, strends, striends. >> > In all case, I think that is better a third parameter and keep underlined.
> Please, not stribegins. We have enough functions with weird names :) > I am ambivalent of the question whether to have additional argument or > two functions, I guess with a slight preference for argument.
The bulk of the time I'm applying this to the SQL query that is going to return a set of results rather than direct to a string. In that case it's STARTING 'xYZ'. Because the need has not arisen I've only just noticed - after 20 odd years - there is no matching ENDING. Although normally one needs to build a phantom field to index the data, so I do have ONE case of reversed_field STARTING 'ZYX'. Is starting just a Firebird SQL thing or is it more generally available. I do a few google searches but as usual when searching for things like 'starting' one gets hundreds of pages on 'running' the software and it's other connotations. I suspect like PHP the other methods of doing things take the strain, so certainly LIKE 'XYZ%' and '%XYZ' are probably the 'generic' solution but suffer from slower search times, especially when looking for the ENDING string.
-- 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 Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

Rowan Collins

10 years ago
On 13/08/2016 08:42, Lester Caine wrote:
> Is starting just a Firebird SQL thing or is it more generally available. > I do a few google searches but as usual when searching for things like > 'starting' one gets hundreds of pages on 'running' the software and it's > other connotations.
I've never come across it in Postgres, MS SQL Server, or MySQL. Generally LIKE 'abc%' is the recommended approach (and will I think hit the index in many cases, because the DBMS can optimize the case of a prefix match if it knows at planning time). A "starting" keyword would certainly be useful if it was there. :) It doesn't quite fill the same need as a PHP function, of course, because you might be checking user input, or API results, or all sorts of things that won't, or haven't yet, hit the database. Currently the common idiom for that is the ugly strpos($string, 'abc') === 0 Regards,
-- Rowan Collins [IMSoP]

Lester Caine

10 years ago
On 18/08/16 12:39, Rowan Collins wrote:
>> Is starting just a Firebird SQL thing or is it more generally available. >> I do a few google searches but as usual when searching for things like >> 'starting' one gets hundreds of pages on 'running' the software and it's >> other connotations. > > I've never come across it in Postgres, MS SQL Server, or MySQL. > Generally LIKE 'abc%' is the recommended approach (and will I think hit > the index in many cases, because the DBMS can optimize the case of a > prefix match if it knows at planning time). A "starting" keyword would > certainly be useful if it was there. :) > > It doesn't quite fill the same need as a PHP function, of course, > because you might be checking user input, or API results, or all sorts > of things that won't, or haven't yet, hit the database. Currently the > common idiom for that is the ugly strpos($string, 'abc') === 0
PHP is never going to be loading millions of records into memory and searching them. That is the job of a database, and while LIKE 'abc%' can be optimised to use an index and speed up results, if the 'abc%' is supplied as a parameter that is not generally possible to prepare the query using an index. While STARTING always knows the matching string is the first characters of the index. While PHP and SQL share a number of alternatives, the SQL versions will have a premium on search time if an index can't be used. I was just wondering if str_starting and str_ending matched better with other string handling options.
-- 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 Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

Lauri Kenttä

10 years ago
Hello, I only saw you mention strpos, preg_match and substr as (slower) alternatives. However, there's already a function called substr_compare which is meant for just this kind of comparisons but which is more general than your RFC. function str_begins($a, $b) { return substr_compare($a, $b, 0, strlen($b)) === 0; } function str_ends($a, $b) { return substr_compare($a, $b, -strlen($b)) === 0; }
-- Lauri Kenttä

Christoph Becker

10 years ago
On 03.08.2016 at 09:59, Lauri Kenttä wrote:
> I only saw you mention strpos, preg_match and substr as (slower) > alternatives. However, there's already a function called substr_compare > which is meant for just this kind of comparisons but which is more > general than your RFC.
Thanks for pointing out substr_compare(), of which I even have not been aware of. And indeed, substr_compare() is perfectly suitable to verify whether a string starts or ends with a certain substring, so, in my opinion, there is no need for the other functions to be added to ext/standard.
-- Christoph M. Becker

Andrew Faulds

10 years ago
Hi Will, will@wkhudgins.info wrote:
> I recently emailed the group about submitting an RFC for str_begins() > and str_ends() functions. The RFC has now been officially submitted and > is viewable at: > > https://wiki.php.net/rfc/add_str_begin_and_end_functions
I like this RFC, I've long wanted a PHP equivalent to JavaScript and the like's .startsWith()/.endsWith(). Two comments, however. Firstly, I'm not sure if having control over case-sensitivity as part of the function is necessary, as you can always lowercase the string yourself. Furthermore, if the user is dealing with non-single-byte strings (e.g. Unicode), traditional byte-by-byte case-insensitive comparison is not going to work properly in all cases (e.g. ß vs. SS). I'd rather we leave case-insensitivity out of the function, and let the user call strtolower() or mb_strtolower(), as the case may be, themselves. Secondly, in JavaScript, .startsWith()[1] and .endsWith()[2] have an extra parameter for specifying the offset into the haystack (in the case of startsWith) or the string length of the haystack (in the case of endsWith). In Python,[3][4] there's *two* extra parameters, to let you clip the haystack from both ends (like with substr, I think). Have you considered these? They could replace the case-sensitivity parameter, perhaps. Thanks for your work! [1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith [2] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith [3] https://docs.python.org/3/library/stdtypes.html?highlight=str.startswith#str.startswith [4] https://docs.python.org/3/library/stdtypes.html?highlight=str.endswith#str.endswith
-- Andrea Faulds https://ajf.me/

Simon J Welsh

10 years ago
> On 2/08/2016, at 8:52 AM, will@wkhudgins.info wrote: > > Hello, > > I recently emailed the group about submitting an RFC for str_begins() and str_ends() functions. The RFC has now been officially submitted and is viewable at: > > https://wiki.php.net/rfc/add_str_begin_and_end_functions > > The github PR may be found at: > > https://github.com/php/php-src/pull/2049 > > Hope to be hearing about this, > > Will
Firstly, the argument ordering is the wrong way round for a string function. String functions — especially search-related ones — are haystack, needle (see strpos, strstr, strcspn, strpbrk, etc). Secondly, I feel like this RFC does need to include that it’s a BC break by introducing new global functions. A quick search shows that SugarCRM[1] already implements str_begin and str_end functions and there’s likely to be other projects that do too. [1]: https://github.com/sugarcrm/sugarcrm_dev/blob/ae189cfa4ed4edd6a4e1e0d9d1d5ec66f46a0b74/include/utils.php#L2082-L2090
-- Simon Welsh

Unnamed Person

10 years ago
On 2016-08-13 04:34, Simon Welsh wrote:
>> On 2/08/2016, at 8:52 AM, will@wkhudgins.info wrote: >> >> Hello, >> >> I recently emailed the group about submitting an RFC for str_begins() >> and str_ends() functions. The RFC has now been officially submitted >> and is viewable at: >> >> https://wiki.php.net/rfc/add_str_begin_and_end_functions >> >> The github PR may be found at: >> >> https://github.com/php/php-src/pull/2049 >> >> Hope to be hearing about this, >> >> Will > > Firstly, the argument ordering is the wrong way round for a string > function. String functions — especially search-related ones — are > haystack, needle (see strpos, strstr, strcspn, strpbrk, etc). > > Secondly, I feel like this RFC does need to include that it’s a BC > break by introducing new global functions. A quick search shows that > SugarCRM[1] already implements str_begin and str_end functions and > there’s likely to be other projects that do too. > > [1]: > https://github.com/sugarcrm/sugarcrm_dev/blob/ae189cfa4ed4edd6a4e1e0d9d1d5ec66f46a0b74/include/utils.php#L2082-L2090 > -- > Simon Welsh
You are correct, functions like strpos and strstr do follow (haystack, needle) but functions like str_replace follow the format (needle, haystack). Because I did these functions with the underscore, it made sense to make the functions follow the format found in other str_* functions. If the functions were changed to be strbegin, stribegin, strend, and striend, then it would make sense to follow the (haystack, needle) format. However, I think adding the underscore greatly improves the readability of these functions. And if the functions are named with an underscore, I think it should follow the format found in the other underscore functions. Good call on the BC break, I had not thought about it breaking userland functions with the same name. -Will

Simon J Welsh

10 years ago
> On 14/08/2016, at 2:47 AM, will@wkhudgins.info wrote: > > On 2016-08-13 04:34, Simon Welsh wrote: >>> On 2/08/2016, at 8:52 AM, will@wkhudgins.info wrote: >>> Hello, >>> I recently emailed the group about submitting an RFC for str_begins() and str_ends() functions. The RFC has now been officially submitted and is viewable at: >>> https://wiki.php.net/rfc/add_str_begin_and_end_functions >>> The github PR may be found at: >>> https://github.com/php/php-src/pull/2049 >>> Hope to be hearing about this, >>> Will >> Firstly, the argument ordering is the wrong way round for a string >> function. String functions — especially search-related ones — are >> haystack, needle (see strpos, strstr, strcspn, strpbrk, etc). >> Secondly, I feel like this RFC does need to include that it’s a BC >> break by introducing new global functions. A quick search shows that >> SugarCRM[1] already implements str_begin and str_end functions and >> there’s likely to be other projects that do too. >> [1]: >> https://github.com/sugarcrm/sugarcrm_dev/blob/ae189cfa4ed4edd6a4e1e0d9d1d5ec66f46a0b74/include/utils.php#L2082-L2090 >> -- >> Simon Welsh > > You are correct, functions like strpos and strstr do follow (haystack, needle) but functions like str_replace follow the format (needle, haystack). Because I did these functions with the underscore, it made sense to make the functions follow the format found in other str_* functions. If the functions were changed to be strbegin, stribegin, strend, and striend, then it would make sense to follow the (haystack, needle) format. However, I think adding the underscore greatly improves the readability of these functions. And if the functions are named with an underscore, I think it should follow the format found in the other underscore functions.
str_replace and str_ireplace are the only str_* functions that don’t take the full string (haystack) as the first argument. str_pad, str_repeat, str_split and str_word_count all take the full string first even if there are other compulsory arguments. Also, these functions are replacements for current usage of strpos/strrpos/substr_compare, so I feel like the argument ordering should match those rather than another function that isn’t closely related in functionality.
> > Good call on the BC break, I had not thought about it breaking userland functions with the same name. > > -Will
-- Simon Welsh

Unnamed Person

7 years ago
Hello all, I submitted this RFC several years ago. I collected a lot of feedback and I have updated the RFC and corresponding github patch. Please see the RFC at https://wiki.php.net/rfc/add_str_begin_and_end_functions and the github patch at https://github.com/php/php-src/pull/2049. I have addressed many concerns (order of arguments, name of functions, multibye support, etc). I plan to move this RFC to a vote in the coming weeks. Thanks, Will

Unnamed Person

7 years ago
I sent this earlier this week without [RFC] in the subject line...since some people might have filters to check the subject line I wanted to send this again with the proper substring in the subject line–to make it clear I intend to take this to a vote in two weeks. Apologies for the duplicate email. -Will On 2019-06-18 14:45, will@wkhudgins.info wrote:

Nikita Popov

7 years ago
On Thu, Jun 20, 2019 at 12:32 AM <will@wkhudgins.info> wrote:
> I sent this earlier this week without [RFC] in the subject line...since > some people might have filters to check the subject line I wanted to > send this again with the proper substring in the subject line–to make it > clear I intend to take this to a vote in two weeks. Apologies for the > duplicate email. > > -Will > > On 2019-06-18 14:45, will@wkhudgins.info wrote: > > Hello all, > > > > I submitted this RFC several years ago. I collected a lot of feedback > > and I have updated the RFC and corresponding github patch. Please see > > the RFC at https://wiki.php.net/rfc/add_str_begin_and_end_functions > > and the github patch at https://github.com/php/php-src/pull/2049. I > > have addressed many concerns > > (order of arguments, name of functions, multibye support, etc). I plan > > to move this RFC to a vote in the coming weeks. > > > > Thanks, > > > > Will >
Unfortunately, this looks like a case where the RFC feedback has made the proposal worse, rather than better :( I think it's easier to start with what I think this proposal should be: There should be just two functions, str_starts_with() and str_ends_with() -- and that's it. The important realization to have here is that these functions are a bit of sugar for an operation that is quite common, but can also be easily implemented with existing functions (using strcmp, strpos or substr, depending on what you like). There is no need for us to cover every conceivable combination, just make the common case more convenient and easier to read. With that in mind: * I believe the "starts with" and "ends with" naming is a lot more canonical, used by Python, Ruby, Java, JavaScript and probably lots more. * In my experience case-insensitive "i" variants of strings functions are used much less, by an order of magnitude. With this being sugar in the first place, I don't think there's a need to cover case-insensitive variations (and from a quick look, these don't seem to be first class methods in other languages either). If we do want to have them, I'd suggest making the names str_starts_with_ci() and str_ends_with_ci(), which is more obvious and harder to miss than str_istarts_with() etc. * Having mb_* variants of these functions doesn't really make sense. I realize that there's this knee-jerk reaction about how if it doesn't have "mb" in the name it's not Unicode compatible, but in this case it's even more wrong than usual. The normal str_starts_with() function is perfectly safe to use on UTF-8 strings, the only difference between it and mb_str_starts_with() is that it's going to be implemented a lot more efficiently. The only case that *might* make some sense is the case-insensitive variant here, because that has some genuine reliance on the character encoding. But then again, this can be handled by case-folding the strings first, something that mbstring is going to do internally anyway. I would happily accept a proposal for str_starts_with() + str_ends_with(), but I'm a lot more apprehensive about adding these 8 new functions. Regards, Nikita

Ben Ramsey

7 years ago
> On Jun 22, 2019, at 10:32, Nikita Popov <nikita.ppv@gmail.com> wrote: > >> On Thu, Jun 20, 2019 at 12:32 AM <will@wkhudgins.info> wrote: >> >> I sent this earlier this week without [RFC] in the subject line...since >> some people might have filters to check the subject line I wanted to >> send this again with the proper substring in the subject line–to make it >> clear I intend to take this to a vote in two weeks. Apologies for the >> duplicate email. >> >> -Will >> >>> On 2019-06-18 14:45, will@wkhudgins.info wrote: >>> Hello all, >>> >>> I submitted this RFC several years ago. I collected a lot of feedback >>> and I have updated the RFC and corresponding github patch. Please see >>> the RFC at https://wiki.php.net/rfc/add_str_begin_and_end_functions >>> and the github patch at https://github.com/php/php-src/pull/2049. I >>> have addressed many concerns >>> (order of arguments, name of functions, multibye support, etc). I plan >>> to move this RFC to a vote in the coming weeks. >>> >>> Thanks, >>> >>> Will >> > > Unfortunately, this looks like a case where the RFC feedback has made the > proposal worse, rather than better :( > > I think it's easier to start with what I think this proposal should be: > There should be just two functions, str_starts_with() and str_ends_with() > -- and that's it. > > The important realization to have here is that these functions are a bit of > sugar for an operation that is quite common, but can also be easily > implemented with existing functions (using strcmp, strpos or substr, > depending on what you like). There is no need for us to cover every > conceivable combination, just make the common case more convenient and > easier to read. > > With that in mind: > * I believe the "starts with" and "ends with" naming is a lot more > canonical, used by Python, Ruby, Java, JavaScript and probably lots more. > * In my experience case-insensitive "i" variants of strings functions are > used much less, by an order of magnitude. With this being sugar in the > first place, I don't think there's a need to cover case-insensitive > variations (and from a quick look, these don't seem to be first class > methods in other languages either). If we do want to have them, I'd suggest > making the names str_starts_with_ci() and str_ends_with_ci(), which is more > obvious and harder to miss than str_istarts_with() etc. > * Having mb_* variants of these functions doesn't really make sense. I > realize that there's this knee-jerk reaction about how if it doesn't have > "mb" in the name it's not Unicode compatible, but in this case it's even > more wrong than usual. The normal str_starts_with() function is perfectly > safe to use on UTF-8 strings, the only difference between it and > mb_str_starts_with() is that it's going to be implemented a lot more > efficiently. The only case that *might* make some sense is the > case-insensitive variant here, because that has some genuine reliance on > the character encoding. But then again, this can be handled by case-folding > the strings first, something that mbstring is going to do internally anyway. > > I would happily accept a proposal for str_starts_with() + str_ends_with(), > but I'm a lot more apprehensive about adding these 8 new functions. > > Regards, > Nikita
I like the idea of simplifying this to the two functions str_starts_with() and str_ends_with(). When I was looking through this the other day, I had trouble coming up with an example of a string with the mb_* versions would ever generate a different result from the non-multibyte versions, since the implementation only needs to count and analyze bytes for uniqueness. Perhaps it would only be an issue with the case-insensitive versions, as Nikita points out? If so, can someone provide some example strings where an mb_starts_with_ci() would return true, while str_starts_with_ci() would return false? I think the case sensitivity versions would be common enough in use cases (i.e. looking to see if a path ends with .CSV vs. .csv, etc.), but maybe the signatures could be revised to pass a third parameter? str_starts_with($haystack, $needle, $case_sensitive = true): bool -Ben

Rowan Collins

7 years ago
On 22 June 2019 20:56:24 BST, Ben Ramsey <ben@benramsey.com> wrote:
>Perhaps it would only be an issue with the case-insensitive versions, >as Nikita points out? If so, can someone provide some example strings >where an mb_starts_with_ci() would return true, while >str_starts_with_ci() would return false?
That's easy: any character that has a lower- and uppercase form, and is not represented as one byte in the target encoding. For that matter, any such character in the non-ASCII section of a single-byte encoding, since a non-mbstring case insensitive flag would presumably leave everything other than ASCII letters untouched. So, any non-Latin script, like Greek or Cyrillic; any accented characters, unless you're lucky and they're represented by ASCII-letter plus combining modifier; the Turkish "i", which if I remember rightly has three forms not two; and so on. Regards,
-- Rowan Collins [IMSoP]

Ben Ramsey

7 years ago
> On Jun 23, 2019, at 05:35, Rowan Collins <rowan.collins@gmail.com> wrote: > > On 22 June 2019 20:56:24 BST, Ben Ramsey <ben@benramsey.com> wrote: >> Perhaps it would only be an issue with the case-insensitive versions, >> as Nikita points out? If so, can someone provide some example strings >> where an mb_starts_with_ci() would return true, while >> str_starts_with_ci() would return false? > > > That's easy: any character that has a lower- and uppercase form, and is not represented as one byte in the target encoding. For that matter, any such character in the non-ASCII section of a single-byte encoding, since a non-mbstring case insensitive flag would presumably leave everything other than ASCII letters untouched. > > So, any non-Latin script, like Greek or Cyrillic; any accented characters, unless you're lucky and they're represented by ASCII-letter plus combining modifier; the Turkish "i", which if I remember rightly has three forms not two; and so on.
According to Google, "İyi akşamlar” is the Turkish phrase for “Good evening” (Turkish speakers, please correct me, if this wrong). However, using the existing mb_* functions, I can’t get mb_stripos() to return 0 when trying to see if the string “İYI AKŞAMLAR” begins with “i̇yi.” I’m just using UTF-8, so maybe there’s an encoding issue here? $string = 'İyi akşamlar'; $upper = mb_strtoupper($string); $lowerChars = mb_strtolower(mb_substr($string, 0, 3)); var_dump($string, $upper, $lowerChars); var_dump(mb_stripos($upper, $lowerChars));

Unnamed Person

7 years ago
These are good points. Originally my RFC called for less functions but based on feedback I added the others. My proposal: take the RFC as-is to a vote. If it fails, I will raise another RFC for a vote that will just contain the two basic functions: str_begins and str_ends. Thanks, Will On 2019-06-22 15:56, Ben Ramsey wrote:

Nikita Popov

7 years ago
On Fri, Jun 28, 2019 at 10:54 PM <will@wkhudgins.info> wrote:
> These are good points. Originally my RFC called for less functions but > based on feedback I added the others. My proposal: take the RFC as-is to > a vote. If it fails, I will raise another RFC for a vote that will just > contain the two basic functions: str_begins and str_ends. >
To put my comments into more actionable form, here is what I would recommend for this RFC: * Rename str_begins -> str_starts_with, str_ends -> str_ends_with, str_ibegins -> str_starts_with_ci, str_iends -> str_ends_with_ci. As mentioned before, this is standard terminology used by many, many programming languages and it would be great if PHP did not deviate from convention without strong reason. * Have a separate vote (in the same RFC) for the addition of the corresponding mb_* variants. I believe doing those two changes will ensure that the core part of the RFC passes. I personally would be voting yes on the first part and no on the second, but others may decide as they see fit. Nikita

Weirdan

7 years ago
On Sat, Jun 22, 2019 at 6:32 PM Nikita Popov <nikita.ppv@gmail.com> wrote:
> > The normal str_starts_with() function is perfectly safe to use on UTF-8 strings,
Only if you assume strings to be normalized to the same form. Checking if NFC string starts with NFD substring by checking them bit by bit is going to yield false negatives [1] [1] https://3v4l.org/4HgUL
-- Best regards, Bruce Weirdan mailto:weirdan@gmail.com

Nikita Popov

7 years ago
On Sat, Jun 22, 2019 at 10:27 PM Bruce Weirdan <weirdan@gmail.com> wrote:
> On Sat, Jun 22, 2019 at 6:32 PM Nikita Popov <nikita.ppv@gmail.com> wrote: > > > > The normal str_starts_with() function is perfectly safe to use on UTF-8 > strings, > > Only if you assume strings to be normalized to the same form. Checking if > NFC > string starts with NFD substring by checking them bit by bit is going > to yield false negatives [1] > > [1] https://3v4l.org/4HgUL >
That's correct, but not really relevant in the context of the discussion, as mbstring does not perform Unicode normalization, so mb_* functions wouldn't change anything about this. (Not that basic string operations should be performing implicit Unicode normalization...) Nikita