This email is just to gauge the response for some syntactic sugar to be
added to PHP in regard to slicing an array.
My proposal is something similar to Pythons slice, in PHP this would look
like:
$slided = $array[1:4]
This will get the elements in positions 1,2,3,4. (1 through 4 inclusive),
ignoring the actual key of the array. The result for an array will be an
array with the keys preserved, in the same order. Any multi-dimensions are
also respected and returned within the array.
This is the same as using the array_slice method with the PRESERVE KEYS
fourth parameter passed through as true.
The result for a string is the string from the two positions indicated.
This is the same as using substr()
.
The benefits for this as I see it is:
- No function overhead
- More readable (opinionated)
- Consistent with how we can select items from an array currently (using
index).
If the array is not long enough (for example, index 4 doesn't exist), then
a NOTICE is thrown, and the values returned are as much as possible; this
would be the same as calling $array[1:] which will get the items in
position 1 through to the end.
If the variable used contains a string, then this will get the values from
the string at those positions. The same way that $string[1] will get the
second character, $string[2:5] will get the third through to the sixth
character. This differs from array_slice which would throw a warning and
return null.
If the variable isn't either a string or an array (or convertible to
either); then a warning is thrown and null is returned, consistent with
current use ($int[0] will return null)
Arrays with associated keys cannot be selected by using the keys they have,
but instead should be selected by the position those keys hold.
For example, this is invalid:
$array['string':'end']. This should throw a fatal error.
The valid options are:
$array[from:to] - This gets the values from position 'from' to 'to'
inclusive
$array[from:] - This gets the values from the position 'from' to the end.
$array[:to] - This gets the values from the start to the position 'to'.
$array[:] will get all the items in the array ($same as doing $array)
A side addition, that may be considered is adding [-1] to get the last item
in the array. But that is not a main part of this RFC.
Thanks
This email is just to gauge the response for some syntactic sugar to be
added to PHP in regard to slicing an array.My proposal is something similar to Pythons slice, in PHP this would look
like:$slided = $array[1:4]
This will get the elements in positions 1,2,3,4. (1 through 4 inclusive),
ignoring the actual key of the array. The result for an array will be an
array with the keys preserved, in the same order. Any multi-dimensions are
also respected and returned within the array.This is the same as using the array_slice method with the PRESERVE KEYS
fourth parameter passed through as true.The result for a string is the string from the two positions indicated.
This is the same as usingsubstr()
.The benefits for this as I see it is:
- No function overhead
- More readable (opinionated)
- Consistent with how we can select items from an array currently (using
index).If the array is not long enough (for example, index 4 doesn't exist), then
a NOTICE is thrown, and the values returned are as much as possible; this
would be the same as calling $array[1:] which will get the items in
position 1 through to the end.If the variable used contains a string, then this will get the values from
the string at those positions. The same way that $string[1] will get the
second character, $string[2:5] will get the third through to the sixth
character. This differs from array_slice which would throw a warning and
return null.If the variable isn't either a string or an array (or convertible to
either); then a warning is thrown and null is returned, consistent with
current use ($int[0] will return null)Arrays with associated keys cannot be selected by using the keys they have,
but instead should be selected by the position those keys hold.For example, this is invalid:
$array['string':'end']. This should throw a fatal error.
The valid options are:
$array[from:to] - This gets the values from position 'from' to 'to'
inclusive
$array[from:] - This gets the values from the position 'from' to the end.
$array[:to] - This gets the values from the start to the position 'to'.$array[:] will get all the items in the array ($same as doing $array)
A side addition, that may be considered is adding [-1] to get the last item
in the array. But that is not a main part of this RFC.Thanks
Variations of this proposal have been discussed many times. I don't
recall what the pushback was but it's worth your time to check the
archives to see what the objections were and if you can address them,
and/or if the new engine in PHP 7 addresses them. (I suspect it
has/will ameliorate a lot of implementation-level issues with old
proposals.)
Personally I'd be in favor of such a syntax but I don't recall the
objections in the past beyond "meh, sugar".
--Larry Garfield
I've had a quick scan of the list at https://wiki.php.net/rfc but cannot
seem to find anything. I'll read more carefully through, or is there a
different list elsewhere which I should look at?
This email is just to gauge the response for some syntactic sugar to be
added to PHP in regard to slicing an array.My proposal is something similar to Pythons slice, in PHP this would look
like:$slided = $array[1:4]
This will get the elements in positions 1,2,3,4. (1 through 4 inclusive),
ignoring the actual key of the array. The result for an array will be an
array with the keys preserved, in the same order. Any multi-dimensions are
also respected and returned within the array.This is the same as using the array_slice method with the PRESERVE KEYS
fourth parameter passed through as true.The result for a string is the string from the two positions indicated.
This is the same as usingsubstr()
.The benefits for this as I see it is:
- No function overhead
- More readable (opinionated)
- Consistent with how we can select items from an array currently (using
index).If the array is not long enough (for example, index 4 doesn't exist), then
a NOTICE is thrown, and the values returned are as much as possible; this
would be the same as calling $array[1:] which will get the items in
position 1 through to the end.If the variable used contains a string, then this will get the values from
the string at those positions. The same way that $string[1] will get the
second character, $string[2:5] will get the third through to the sixth
character. This differs from array_slice which would throw a warning and
return null.If the variable isn't either a string or an array (or convertible to
either); then a warning is thrown and null is returned, consistent with
current use ($int[0] will return null)Arrays with associated keys cannot be selected by using the keys they
have,
but instead should be selected by the position those keys hold.For example, this is invalid:
$array['string':'end']. This should throw a fatal error.
The valid options are:
$array[from:to] - This gets the values from position 'from' to 'to'
inclusive
$array[from:] - This gets the values from the position 'from' to the end.
$array[:to] - This gets the values from the start to the position 'to'.$array[:] will get all the items in the array ($same as doing $array)
A side addition, that may be considered is adding [-1] to get the last
item
in the array. But that is not a main part of this RFC.Thanks
Variations of this proposal have been discussed many times. I don't
recall what the pushback was but it's worth your time to check the archives
to see what the objections were and if you can address them, and/or if the
new engine in PHP 7 addresses them. (I suspect it has/will ameliorate a
lot of implementation-level issues with old proposals.)Personally I'd be in favor of such a syntax but I don't recall the
objections in the past beyond "meh, sugar".--Larry Garfield
I've had a quick scan of the list at https://wiki.php.net/rfc but cannot
seem to find anything. I'll read more carefully through, or is there a
different list elsewhere which I should look at?
Not everything makes it to an RFC. This list's archives are quite
extensive. (People here are verbose):
http://php.net/mailing-lists.php
http://marc.info/?l=php-internals
Also, no top-posting, please.
--Larry Garfield
I've had a quick scan of the list at https://wiki.php.net/rfc but cannot
seem to find anything. I'll read more carefully through, or is there a
different list elsewhere which I should look at?Not everything makes it to an RFC. This list's archives are quite
extensive. (People here are verbose):http://php.net/mailing-lists.php
http://marc.info/?l=php-internalsAlso, no top-posting, please.
--Larry Garfield
--
Apologies about the top post, that was gmail automatically hiding the main
content so I just typed. Thanks for the links. I will look through them now
to find some proposals which have failed before; and try to improve this
one. Still would like feedback from anybody else reading this too. Thanks.
Variations of this proposal have been discussed many times. I don't
recall what the pushback was but it's worth your time to check the archives
to see what the objections were and if you can address them, and/or if the
new engine in PHP 7 addresses them. (I suspect it has/will ameliorate a
lot of implementation-level issues with old proposals.)
I've tried implementing python style slice on both strings and arrays in
the past (I don't seem to have an existing branch with it in any more
though it seems). The biggest problems I hit were regarding the syntax, the
functionality itself worked.
Colons caused problems with ternary operators in the lexer, and I had an
issue with commas too, but I forget what it was. Of course these might have
been resolvable, but I didn't put too much effort into it.
I've tried implementing python style slice on both strings and arrays in
the past (I don't seem to have an existing branch with it in any more
though it seems). The biggest problems I hit were regarding the syntax, the
functionality itself worked.Colons caused problems with ternary operators in the lexer, and I had an
issue with commas too, but I forget what it was. Of course these might have
been resolvable, but I didn't put too much effort into it.
That said, I'm a little older and wiser than I was then, I'd still be
interested in looking at this. I'll try and come up with something that
works over the weekend.
That said, I'm a little older and wiser than I was then, I'd still be
interested in looking at this. I'll try and come up with something that
works over the weekend.
I started on the code last night, but didn't get very far. I got it to
match the T_COLON, but no logic or parsing has been done yet. I am still a
bit shaky on how to implement this, so would definitely appreciate the help
I've tried implementing python style slice on both strings and arrays in
the past (I don't seem to have an existing branch with it in any more
though it seems). The biggest problems I hit were regarding the syntax, the
functionality itself worked.
If you've got a link to your messaging thread, I'd love to read it. Thanks
Colons caused problems with ternary operators in the lexer, and I had an
issue with commas too, but I forget what it was. Of course these might have
been resolvable, but I didn't put too much effort into it.
Could this not be mitigated by adding a new token like T_COLON to be used
to match this use case?
I've tried implementing python style slice on both strings and arrays in
the past (I don't seem to have an existing branch with it in any more
though it seems). The biggest problems I hit were regarding the syntax,
the
functionality itself worked.If you've got a link to your messaging thread, I'd love to read it. Thanks
Colons caused problems with ternary operators in the lexer, and I had an
issue with commas too, but I forget what it was. Of course these might
have
been resolvable, but I didn't put too much effort into it.Could this not be mitigated by adding a new token like T_COLON to be used
to match this use case?
The only thing I could find is:
http://chat.stackoverflow.com/transcript/11?m=15926856#15926856
If your branch is available on github let me know, more than happy work on
it with you.
If your branch is available on github let me know, more than happy work on
it with you.
I'll publish it tonight (GMT), I'm at work at the moment.
Thanks!
My proposal is something similar to Pythons slice, in PHP this would look
like:$slided = $array[1:4]
This will get the elements in positions 1,2,3,4. (1 through 4 inclusive),
ignoring the actual key of the array. The result for an array will be an
array with the keys preserved, in the same order.
While I can see the reasoning for not looking into the actual keys
(which might not have a logically sliceable order), I think the syntax
needs to be more distinct, because this seems a bit confusing:
$countdown = [ 5 => 'Five!', 4 => 'Four!', 3 => 'Three!', 2 => 'Two!', 1
=> 'One!', 0 => 'Zero!' ]
$countdown[0]; // 'Zero!'
$countdown[0:0]; // ['Five!']
$countdown[0:][0] // 'Zero!'
$countdown[:0][0] // null - slice contains no key 0
The problem is that the slice access looks like an extension of key
access, but is actually a new concept of positional element access. With
a slight tweak to syntax, such as adding an @, we could make positional
access available for non-slices as well:
reset($countdown); // Five! - a common way of getting the first element
positionally
$countdown[@0]; // 'Five!'
$countdown[@1]; // 'Four!'
$countdown[@0:0] // ['Five!']
$countdown[@0:1] // ['Five!', 'Four!']
$countdown[@0:][@0] // 'Five!'
$countdown[@:0][@0] // 'Five!'
A side addition, that may be considered is adding [-1] to get the last item
in the array. But that is not a main part of this RFC.
This would actually be a really important addition for me, but only if I
can do it on a non-slice, as above:
$countdown[-1]; // null - no such key
end($countdown); // 'Zero!' - common way of getting last element
$countdown[@-1]; // 'Zero!' - positional access counting from the end
$countdown[@-2]; // 'One!' - fiddly to do in current PHP
I just wrote out all those examples and realised that it may not be
possible to reuse @ in this context. Finding new symbols to use for
syntax is hard. :(
Regards,
--
Rowan Collins
[IMSoP]
My proposal is something similar to Pythons slice, in PHP this would look
like:$slided = $array[1:4]
This will get the elements in positions 1,2,3,4. (1 through 4 inclusive),
ignoring the actual key of the array. The result for an array will be an
array with the keys preserved, in the same order.While I can see the reasoning for not looking into the actual keys (which
might not have a logically sliceable order), I think the syntax needs to be
more distinct, because this seems a bit confusing:$countdown = [ 5 => 'Five!', 4 => 'Four!', 3 => 'Three!', 2 => 'Two!', 1
=> 'One!', 0 => 'Zero!' ]$countdown[0]; // 'Zero!'
$countdown[0:0]; // ['Five!']
$countdown[0:][0] // 'Zero!'
$countdown[:0][0] // null - slice contains no key 0The problem is that the slice access looks like an extension of key
access, but is actually a new concept of positional element access. With a
slight tweak to syntax, such as adding an @, we could make positional
access available for non-slices as well:reset($countdown); // Five! - a common way of getting the first element
positionally
$countdown[@0]; // 'Five!'
$countdown[@1]; // 'Four!'
$countdown[@0:0] // ['Five!']
$countdown[@0:1] // ['Five!', 'Four!']
$countdown[@0:][@0] // 'Five!'
$countdown[@:0][@0] // 'Five!'A side addition, that may be considered is adding [-1] to get the last
item
in the array. But that is not a main part of this RFC.This would actually be a really important addition for me, but only if I
can do it on a non-slice, as above:$countdown[-1]; // null - no such key
end($countdown); // 'Zero!' - common way of getting last element
$countdown[@-1]; // 'Zero!' - positional access counting from the end
$countdown[@-2]; // 'One!' - fiddly to do in current PHPI just wrote out all those examples and realised that it may not be
possible to reuse @ in this context. Finding new symbols to use for syntax
is hard. :(Regards,
--
Rowan Collins
[IMSoP]--
While I can see the reasoning for not looking into the actual keys (which
might not have a logically sliceable order), I think the syntax needs to be
more distinct, because this seems a bit confusing:
$countdown = [ 5 => 'Five!', 4 => 'Four!', 3 => 'Three!', 2 => 'Two!', 1
=> 'One!', 0 => 'Zero!' ]
$countdown[0]; // 'Zero!'
$countdown[0:0]; // ['Five!']
$countdown[0:][0] // 'Zero!'
$countdown[:0][0] // null - slice contains no key 0
Thats a good point, something else that just came to me; your example of
$countdown[0:0]; if we had it as inclusive indexes, then this would
actually give you ['Five!', 'Five!'], which is unlikely to be what was
desired. What would be a good solution to this?
- The range cannot be 0 in length (such that, from - to must be > 0) -
This would also get around issues of people trying to use it like so :
$countdown[5:3], as the expected outcome of that should be a fatal error.
Also, your use-case of 0:0 would be better placed simply using
$countdown[0].
The issue with this solution would then come that if there was any code
for this range being dynamic, some logic would have to take place on the
users side to ensure that $from and $to differ by at least +1
To me, this isn't really a big issue, since I cannot see this being that
big of a use case, but it is worth mentioning.
To me, a larger use case would be a user wanting say, the first N items
from an array, and so using $sub_array = $array[: (N-1)], which can then be
easily used within a foreach loop, without the need for $key to be used and
breaking out of the foreach loop on the Nth iteration.
The problem is that the slice access looks like an extension of key access,
but is actually a new concept of positional element access. With a slight
tweak to syntax, such as adding an @, we could make positional access
available for non-slices as well:
I think the use of the @ symbol would be misplaced for this; it already has
a meaning within PHP, and many people are often taught to shy away from it
(due to previous bad coding practices using it heavily); and so this
feature might suffer by association even though the symbol means something
completely different.
A different symbol is certainly a possibility; but this is something that
happens nowhere else (ignoring the & by reference) in PHP, and feels like
it isn't the best solution to the problem.
Other languages that implement this do not require a prefixed symbol, and I
don't see the need for PHP to have one. There may be some confusion; but
that will be displaced over time.
- Would a possible solution to this be just to make it explicitly clear in
the documentation that this does not refer to the keys, and instead the
array positions?
A side addition, that may be considered is adding [-1] to get the last
item
in the array. But that is not a main part of this RFC.
This would actually be a really important addition for me, but only if I
can do it on a non-slice, as above:
To me, whilst I certainly want this part in it, I don't want to overload
the RFC with things that aren't core to the feature, which may be cause for
rejection if it makes it to a vote; I may do this as a successor-vote. Feel
free to make it its own RFC if you want.
Thats a good point, something else that just came to me; your example
of $countdown[0:0]; if we had it as inclusive indexes, then this would
actually give you ['Five!', 'Five!'], which is unlikely to be what was
desired.
I'm not sure why it would duplicate the item like that. My
interpretation of $array[$start:$end] would be "an array containing all
those elements of $array with a position more than or equal to $start,
but less than or equal to $end" ($position >= $start && $position <= $end).
Under that interpretation, $array[0:0] is a valid slice, of length 1,
which would contain only the element of $array with position 0 (0 >= 0
&& 0 <= 0).
Since you propose to preserve keys in the slice, it's actually
impossible to have a duplicate item in the output anyway: if you were
right and it selected the first item twice, you'd get [5 => 'Five!', 5
=> 'Five!'], but keys are unique by definition, so it would end up
stored as [5 => 'Five!'].
- The range cannot be 0 in length (such that, from - to must be > 0)
- This would also get around issues of people trying to use it like so
: $countdown[5:3], as the expected outcome of that should be a fatal
error.
$countdown[0:0] is a slice of length 1, not 0, just as $countdown[0:1]
is a slice of length 2, not 1. Under my proposed definition,
$countdown[5:3] could simply always return an empty array, since there
is no value of $position such that ($position >= 5 && $position <= 3).
Also, your use-case of 0:0 would be better placed simply using
$countdown[0].
Check my example again. $countdown[0] refers to the element with key 0,
so is absolutely not a replacement for $countdown[0:0]. This is the
whole point of my example.
I think the use of the @ symbol would be misplaced for this
To be clear, @ was just the first idea that came to mind, not central to
my point. The point is to first create syntax for "positional access",
and then extend that to "positional slice access".
A different symbol is certainly a possibility; but this is something
that happens nowhere else (ignoring the & by reference) in PHP, and
feels like it isn't the best solution to the problem.
I'm not sure what you mean by "something that happens nowhere else" PHP
has syntax for all sorts of things, using all sorts of symbols. Your own
suggestion uses the : symbol in a place where it currently can't exist.
Other languages that implement this do not require a prefixed symbol,
and I don't see the need for PHP to have one.
Most languages don't need to worry about an "array" type which has keys
independent from their position. PHP is the only language I know where
the 0 in $foo[0] does not refer to the position in the array, but a key
which can appear at any position.
- Would a possible solution to this be just to make it explicitly
clear in the documentation that this does not refer to the keys, and
instead the array positions?
To my mind, no. Manual pages about syntax features are hard to find
unless you know exactly what that syntax feature is called, and
documenting an inconsistency is no substitute for avoiding that
inconsistency in the first place.
Regards,
--
Rowan Collins
[IMSoP]
I'm not sure why it would duplicate the item like that. My interpretation
of $array[$start:$end] would be "an array containing all those elements of
$array with a position more than or equal to $start, but less than or equal
to $end" ($position >= $start && $position <= $end).
I agree with this statement now, I was misinterpreting how I thought it
should work, but reading this; I think you're right. Also, your next point
about the unique array indexes covers it anyway, so it doesn't really
matter regardless.
Check my example again. $countdown[0] refers to the element with key 0, so
is absolutely not a replacement for $countdown[0:0]. This is the whole
point of my example.
You're correct, this was my mistake.
I'm not sure what you mean by "something that happens nowhere else" PHP has
syntax for all sorts of things, using all sorts of symbols. Your own
suggestion uses the : symbol in a place where it currently can't exist.
What I mean by 'symbol' here, is a prefix to tell it what the context of
its use is; in this case, it is the declaration that we are requiring the
index not the key. As far as I'm aware, and can think of at the moment, PHP
has nothing like a hinter symbol.
The only purpose of this symbol is to tell the user that it is indexes not
keys.
Maybe there should be a symbol to declare that, but i'm not sure. Will
appreciate more comments on this.
If we go the direction of using a symbol, what should be the outcome of the
symbol missing? fatal error, or to try to slice based on the keys?
I'm not sure what you mean by "something that happens nowhere else" PHP
hassyntax for all sorts of things, using all sorts of symbols. Your own
suggestion uses the : symbol in a place where it currently can't
exist.What I mean by 'symbol' here, is a prefix to tell it what the context
of
its use is; in this case, it is the declaration that we are requiring
the
index not the key. As far as I'm aware, and can think of at the moment,
PHP
has nothing like a hinter symbol.The only purpose of this symbol is to tell the user that it is indexes
not
keys.
The @ symbol in my examples is not a special marker that is meaningful on its own; the parser wouldn't even see it as a separate token. The syntax for key access is $array[$key], the syntax for positional access would be $array[@$position]; chosen to look similar, but one is not a special case of the other.
The syntax needn't be just an extra character, we could invent something else, like $array[[$position]], or $array@($position), though I can't think of anything I like.
Similarly, your suggested slice syntax is chosen to look similar to key access, and to the same feature in other languages, but since it doesn't exist yet, we can make up whatever parser rules we want.
Maybe there should be a symbol to declare that, but i'm not sure. Will
appreciate more comments on this.If we go the direction of using a symbol, what should be the outcome of
the
symbol missing? fatal error, or to try to slice based on the keys?
The symbol isn't something that can be missing, it's just part of the syntax, so this is like saying "what should we do if the closing ] is missing?" The answer is, nothing, it's undefined syntax, so it's a parse error.
You could implement slicing on keys, and if you did so, [x:y] would be the obvious syntax to use, but as you've said of negative positions, let's keep to one feature at a time.
Regards,
Rowan Collins
[IMSoP]
The @ symbol in my examples is not a special marker that is meaningful on
its own; the parser wouldn't even see it as a separate token. The syntax
for key access is $array[$key], the syntax for positional access would be
$array[@$position]; chosen to look similar, but one is not a special case
of the other.
Ah, I understand you now. Yes I agree that this would be useful then. It
allows us the future possibility of a separate RFC looking into slicing on
keys as mentioned at the bottom of your post.
The syntax needn't be just an extra character, we could invent something
else, like $array[[$position]], or $array@($position), though I can't
think of anything I like.
I think for simplicity, we should keep it as $array[], and have a symbol
within it that shows that it is an internal index rather than the key. An
Asterisk (*) is my preference at the moment, though caret also looks
promising.
Here are some examples of how various characters could look
$array[1:3], $array[:], $array[*:1], $array[*1:]
$array[@1:3], $array[@:], $array[@:1], $array[@1:]
$array[^1:3], $array[^:], $array[^:1], $array[^1:]
$array[&1:3], $array[&:], $array[&:1], $array[&1:]
The symbol isn't something that can be missing, it's just part of the
syntax, so this is like saying "what should we do if the closing ] is
missing?" The answer is, nothing, it's undefined syntax, so it's a parse
error.
So a parse error currently, and a future RFC can define the terms of using
this normally?
If we go down the route of adding a symbol for by index rather than by key,
then this RFC should also include the normal getting array by key style,
without the colon range operator.
For example:
$array[*1] to get the item that is the second in the list, rather than at
key 1.
Alex Bowers wrote on 20/03/2015 11:38:
The @ symbol in my examples is not a special marker that is meaningful on its own; the parser wouldn't even see it as a separate token. The syntax for key access is $array[$key], the syntax for positional access would be $array[@$position]; chosen to look similar, but one is not a special case of the other.
Ah, I understand you now. Yes I agree that this would be useful then.
It allows us the future possibility of a separate RFC looking into
slicing on keys as mentioned at the bottom of your post.The syntax needn't be just an extra character, we could invent something else, like $array[[$position]], or $array@($position), though I can't think of anything I like.
I think for simplicity, we should keep it as $array[], and have a
symbol within it that shows that it is an internal index rather than
the key. An Asterisk (*) is my preference at the moment, though caret
also looks promising.Here are some examples of how various characters could look
$array[1:3], $array[:], $array[*:1], $array[*1:]
$array[@1:3], $array[@:], $array[@:1], $array[@1:]
$array[^1:3], $array[^:], $array[^:1], $array[^1:]
$array[&1:3], $array[&:], $array[&:1], $array[&1:]The symbol isn't something that can be missing, it's just part of the syntax, so this is like saying "what should we do if the closing ] is missing?" The answer is, nothing, it's undefined syntax, so it's a parse error.
So a parse error currently, and a future RFC can define the terms of
using this normally?If we go down the route of adding a symbol for by index rather than by
key, then this RFC should also include the normal getting array by key
style, without the colon range operator.For example:
$array[*1] to get the item that is the second in the list, rather than
at key 1.
Yep, I think we're on the same page now.
There's basically three ways of selecting items - by key, by position
from start, and by position from end - and two types of selection - a
single element, or an array of zero or more elements. That gives us 6
possible combinations, which (using the @ notation for consistency with
previous examples) would be:
Select by key:
Single element: $array[$x] - existing syntax
Slice: $array[$a:$b] - equivalent to a filter asserting $key >= $a &&
$key <= $b
Select by position from start:
Single element: $array[@$x]
Slice: $array[@$a:$b],$array[@$a:], and $array[@:$b]
Select by position from end - as above, but using negative indexes:
Single element: $array[@-$x] - equivalent to $array[@length($array)-$x]
Slice: $array[@-$a:-$b] - equivalent to
$array[@length($array)-$a:length($array)-$b]
Several of these are actually rather hard to do with current PHP features:
- you can get the first element with
reset()
and the last withend()
,
but arbitrary position selection is harder - there is no version of array_filter for testing keys, and being able
to write $dictionary['elephant':'snake'] would actually be pretty handy
Actually, the only one that's easy to emulate (apart from the obvious
single element by key) is the one you propose to add first - getting a
positional slice of an array, which array_slice(..., true) already does.
Regards,
Rowan Collins
[IMSoP]
We also need to consider then the possibility of setting data by position.
What should $array[@1:3] = [1,2,3] do?
Should it overwrite the values there, and append any that don't exist, or
should it be a parse error?
We also need to consider then the possibility of setting data by position.
What should $array[@1:3] = [1,2,3] do?
Should it overwrite the values there, and append any that don't exist, or
should it be a parse error?
I'd say overwrite/replace the range with the new value.
Alex Bowers wrote on 20/03/2015 12:32:
We also need to consider then the possibility of setting data by position.
What should $array[@1:3] = [1,2,3] do?
Should it overwrite the values there, and append any that don't exist,
or should it be a parse error?
Good catch. I guess it could delete the range and replace with the new
value, regardless of size - then you could remove elements from an array
with it, too:
$array[@1:3] = []; // Remove the second through fourth element
$array['x':'z'] = []; // Remove all elements with keys between 'x' and
'z', inclusive
Not sure how that compares to other languages with similar syntax.
It would be kind of cool if it applied to string subscripts as well:
$version = 'PHP 5.6.1';
$version{4:} = '7!';
echo $version; // 'PHP 7!'
Regards,
Rowan Collins
[IMSoP]
$version{4:} = '7!';
I'm sure this is a slight oversight on your end, but just to check. The
change of using {} instead of [] is not because its a string, and is just a
typo / example correct?
Alex Bowers wrote on 20/03/2015 13:09:
On 20 March 2015 at 13:04, Rowan Collins <rowan.collins@gmail.com
mailto:rowan.collins@gmail.com> wrote:$version{4:} = '7!';
I'm sure this is a slight oversight on your end, but just to check.
The change of using {} instead of [] is not because its a string, and
is just a typo / example correct?
It's an alternative syntax, which I thought was only usable for string
indexing [1] but is apparently legal on arrays as well [2].
I personally like the idea of string offsets having similar but slightly
different syntax from array offsets, to make clear which you're using. I
use {} instead of [] for that reason, but at the moment the syntaxes are
completely interchangeable as far as I can tell.
[1]
http://php.net/manual/en/language.types.string.php#language.types.string.substr
[2]
http://php.net/manual/en/language.types.array.php#language.types.array.syntax.accessing
Regards,
Rowan Collins
[IMSoP]
It's an alternative syntax
Learn something new every day.
I guess this RFC will need to support both then for consistency reasons; so
it will be down to the end user to determine how they want to separate them
if they choose to. But I don't think we should only match {} for strings
and [] for arrays, that seems broken to me.
Hi Alex,
But I don't think we should only match {} for strings and [] for arrays,
that seems broken to me.
Certainly it breaks BC (and would presumably have to wait until PHP 8), but
if we were starting from scratch today, why would it make sense to have two
syntaxes that do exactly the same thing?
Vik
Certainly it breaks BC (and would presumably have to wait until PHP 8), but
if we were starting from scratch today, why would it make sense to have two
syntaxes that do exactly the same thing?
Maybe you misunderstand me, I am against using two syntaxes for different
things.
Hi Alex,
But I don't think we should only match {} for strings and [] for arrays,
that seems broken to me.
Maybe you misunderstand me, I am against using two syntaxes for different
things.
Based on your reply; yes, I'm definitely misunderstanding! In summary, we
already have two different operations:
(1) Accessing an array's element using subscript notation, eg:
$foo = array('bar'); var_dump($foo[0]); // string(3) "bar"
(2) Accessing a string's character using subscript notation, eg:
$foo = 'bar'; var_dump($foo[0]); // string(1) "b"
And we already have two different syntaxes: $var[$offset] and $var{$offset}.
So we have two syntaxes that each perform two operations. Are we in
agreement that this isn't a good thing?
Sorry that this is all a little off-topic, but I'm interested in people's
opinions because I'm considering a future RFC. My proposition would be to
restrict the two subscript syntaxes to one operation each. And if your slice
sugar RFC aims to augment the functionality of either one or both of these
syntaxes, then that's relevant to me.
Vik
When you say restrict to one each. Do you mean one for strings and one for
arrays?
If so I'd have to disagree with this, since having the same operation
available to both is less likely to give mistakes. Can you give an example
of an actual benefit for this? Since this would cause a backwards
incompatible change. I can't imagine many places if any use the curly
brackets for arrays or strings, but since it exists there may be people
using it. Changing the behaviour of this to only work for one of the two
options seems unnecessary in the name of making code slightly more apparent
on initial reading. But variable names and so on should be used to help
distinguish from array or strings anyway.
Hi Alex,
But I don't think we should only match {} for strings and [] for arrays,
that seems broken to me.Maybe you misunderstand me, I am against using two syntaxes for different
things.Based on your reply; yes, I'm definitely misunderstanding! In summary, we
already have two different operations:(1) Accessing an array's element using subscript notation, eg:
$foo = array('bar'); var_dump($foo[0]); // string(3) "bar"(2) Accessing a string's character using subscript notation, eg:
$foo = 'bar'; var_dump($foo[0]); // string(1) "b"And we already have two different syntaxes: $var[$offset] and
$var{$offset}.So we have two syntaxes that each perform two operations. Are we in
agreement that this isn't a good thing?Sorry that this is all a little off-topic, but I'm interested in people's
opinions because I'm considering a future RFC. My proposition would be to
restrict the two subscript syntaxes to one operation each. And if your
slice
sugar RFC aims to augment the functionality of either one or both of these
syntaxes, then that's relevant to me.Vik
Alex,
When you say restrict to one each. Do you mean one for strings and one for
arrays?
Yes, that's what I mean. I would propose square brackets for array offsets,
and curly braces for strings.
If so I'd have to disagree with this, since having the same operation
available to both is less likely to give mistakes. Can you give an example
of an actual benefit for this? Since this would cause a backwards
incompatible change. I can't imagine many places if any use the curly
brackets for arrays or strings, but since it exists there may be people
using it. Changing the behaviour of this to only work for one of the two
options seems unnecessary in the name of making code slightly more
apparent on initial reading. But variable names and so on should be used
to help distinguish from array or strings anyway.
Yes, I'm very conscious of the substantial BC break, which is why I would
target PHP 8 (or even 9, following a deprecation cycle). I guess you and I
disagree on the benefits of syntax that is more self-documenting. The vast
majority of PHP developers don't use variable names to indicate data types;
the only common convention I've seen is for arrays' names to be pluralized
(ie. $items, $rows etc.), but this doesn't really help. Often when less-
experienced developers come across code that uses subscript syntax on a
variable, they typically assume that the variable is an array (since string
offsets are so much less common), and in doing so, introduce bugs. If the
use of curly-braces was mandatory for string offsets, then code like this
couldn't be mistaken for anything else.
Vik
Yes, I'm very conscious of the substantial BC break, which is why I would
target PHP 8 (or even 9, following a deprecation cycle).
I would guess PHP 8, since you can deprecate things at 7.x
Either way, if you make this a separate thread so we don't get off topic,
and i'm sure you'll get many responses from people who want to have their
say.
Hi Rowan,
I personally like the idea of string offsets having similar but slightly
different syntax from array offsets, to make clear which you're using. I
use {} instead of [] for that reason, but at the moment the syntaxes are
completely interchangeable as far as I can tell.
I'm in exactly the same situation; I'd thought for ages that the curly-brace
syntax was only valid for string offsets, so I use them in favour of square
brackets to avoid confusion.
I'd support reserving curly-braces for string offsets only (and vice-versa
for square brackets / arrays).
One awkward edge-case is where a class implements both __toString() and
ArrayAccess. It would be nice if you could distinguish which type of offset
you're accessing without casting.
Theoretical phpt test: http://pastebin.com/9b6YLC29
Vik
$array['x':'z'] = []; // Remove all elements with keys between 'x' and
'z', inclusive
I believe i mentioned in the past about strings not being allowed for
ranges, since there is no real way to check this (and this appears to be by
key not by index) which should be a separate RFC thread, assuming this one
gets accepted to be expanded upon.
Alex Bowers wrote on 20/03/2015 12:32:
We also need to consider then the possibility of setting data by position.
What should $array[@1:3] = [1,2,3] do?
Should it overwrite the values there, and append any that don't exist, or
should it be a parse error?Good catch. I guess it could delete the range and replace with the new
value, regardless of size - then you could remove elements from an array
with it, too:$array[@1:3] = []; // Remove the second through fourth element
$array['x':'z'] = []; // Remove all elements with keys between 'x' and
'z', inclusiveNot sure how that compares to other languages with similar syntax.
It would be kind of cool if it applied to string subscripts as well:
$version = 'PHP 5.6.1';
$version{4:} = '7!';
echo $version; // 'PHP 7!'Regards,
Rowan Collins
[IMSoP]
Alex Bowers wrote on 20/03/2015 13:10:
$array['x':'z'] = []; // Remove all elements with keys between 'x' and 'z', inclusive
I believe i mentioned in the past about strings not being allowed for
ranges, since there is no real way to check this (and this appears to
be by key not by index) which should be a separate RFC thread,
assuming this one gets accepted to be expanded upon.
I'm carrying over my syntax from previous examples - [a:b] meaning a
key-based slice (which implies accepting string keys, because there's no
reason not to) vs [@a:b] meaning a positional slice. See my earlier mail
on the 6 different types of access - I do realise you're not planning to
implement them all, just playing with the implications of different
decisions if we carry them through consistently in the future.
Regards,
Rowan Collins
[IMSoP]
Okay,
Still not sure how we can implement a range of strings. But since thats for
a different feature, I'll leave that issue for now.
In the list you provided, all of the ones for positional slicing will
definitely be implemented.
Question: What would be the best name for this feature? I do like positional
slicing, but I'm sure there are better names out there. Since it isn't
exclusively array based, and is entirely based on the index position (not
key), positional slicing makes sense, and allows for the future to have key
slicing implemented with their own separate documentation pages provided
and clear naming for the differences between them.
Alex Bowers wrote on 20/03/2015 13:10:
$array['x':'z'] = []; // Remove all elements with keys between 'x' and
'z', inclusive
I believe i mentioned in the past about strings not being allowed for
ranges, since there is no real way to check this (and this appears to be by
key not by index) which should be a separate RFC thread, assuming this one
gets accepted to be expanded upon.I'm carrying over my syntax from previous examples - [a:b] meaning a
key-based slice (which implies accepting string keys, because there's no
reason not to) vs [@a:b] meaning a positional slice. See my earlier mail on
the 6 different types of access - I do realise you're not planning to
implement them all, just playing with the implications of different
decisions if we carry them through consistently in the future.Regards,
Rowan Collins
[IMSoP]
Alex Bowers wrote on 20/03/2015 13:40:
Still not sure how we can implement a range of strings. But since
thats for a different feature, I'll leave that issue for now.
I can't resist a quick answer: if you can define a key-based slice at
all, you can define it for both integer and string keys. Bear in mind
the a:b here isn't a range, it's just a pair of values specifying which
items to include in the slice.
If the definition of a key-based slice is "all elements whose key
satisfies $key >= $a && $key <= $b", then you're just doing comparisons
between strings, which are defined as lexical order. So
$dictionary['elephant':'snake'] returns all elements with keys which
sort lexically between 'elephant' and 'snake', regardless of whether the
array is sorted.
Alternatively, a key-based slice could look up the position in the array
of the two keys, and then perform a positional slice between those
positions, i.e. $array[$a:$b] == $array[ @ key_position($array, $a) :
key_position($array, $b) ]. I'm not sure that's particularly intuitive
or useful, but again, it has no problem with string keys.
Regards,
Rowan Collins
[IMSoP]
So $dictionary['elephant':'snake'] returns all elements with keys which
sort lexically between 'elephant' and 'snake', regardless of whether the
array is sorted.
Makes sense to me.
Alternatively, a key-based slice could look up the position in the array of
the two keys, and then perform a positional slice between those positions,
i.e. $array[$a:$b] == $array[ @ key_position($array, $a) :
key_position($array, $b) ]. I'm not sure that's particularly intuitive or
useful, but again, it has no problem with string keys.
I'd say no to that, since it is not an obvious use case, since if you are
defining associated arrays, going for the indexes of those fields feels
strange; since one of the major benefits to associated keys is that the
order doesn't matter anymore. Having this one feature order dependant
whilst using the associated keys isn't correct in my view.
Alex Bowers wrote on 20/03/2015 13:40:
Still not sure how we can implement a range of strings. But since thats
for a different feature, I'll leave that issue for now.I can't resist a quick answer: if you can define a key-based slice at all,
you can define it for both integer and string keys. Bear in mind the a:b
here isn't a range, it's just a pair of values specifying which items to
include in the slice.If the definition of a key-based slice is "all elements whose key
satisfies $key >= $a && $key <= $b", then you're just doing comparisons
between strings, which are defined as lexical order. So
$dictionary['elephant':'snake'] returns all elements with keys which sort
lexically between 'elephant' and 'snake', regardless of whether the array
is sorted.Alternatively, a key-based slice could look up the position in the array
of the two keys, and then perform a positional slice between those
positions, i.e. $array[$a:$b] == $array[ @ key_position($array, $a) :
key_position($array, $b) ]. I'm not sure that's particularly intuitive or
useful, but again, it has no problem with string keys.Regards,
Rowan Collins
[IMSoP]
So $dictionary['elephant':'snake'] returns all elements with keys which
sort lexically between 'elephant' and 'snake', regardless of whether the
array is sorted.Makes sense to me.
Alternatively, a key-based slice could look up the position in the array
ofthe two keys, and then perform a positional slice between those
positions,
i.e. $array[$a:$b] == $array[ @ key_position($array, $a) :
key_position($array, $b) ]. I'm not sure that's particularly intuitive
or
useful, but again, it has no problem with string keys.I'd say no to that, since it is not an obvious use case, since if you are
defining associated arrays, going for the indexes of those fields feels
strange; since one of the major benefits to associated keys is that the
order doesn't matter anymore. Having this one feature order dependant
whilst using the associated keys isn't correct in my view.Alex Bowers wrote on 20/03/2015 13:40:
Still not sure how we can implement a range of strings. But since thats
for a different feature, I'll leave that issue for now.I can't resist a quick answer: if you can define a key-based slice at
all,
you can define it for both integer and string keys. Bear in mind the a:b
here isn't a range, it's just a pair of values specifying which items to
include in the slice.If the definition of a key-based slice is "all elements whose key
satisfies $key >= $a && $key <= $b", then you're just doing comparisons
between strings, which are defined as lexical order. So
$dictionary['elephant':'snake'] returns all elements with keys which
sort
lexically between 'elephant' and 'snake', regardless of whether the
array
is sorted.Alternatively, a key-based slice could look up the position in the array
of the two keys, and then perform a positional slice between those
positions, i.e. $array[$a:$b] == $array[ @ key_position($array, $a) :
key_position($array, $b) ]. I'm not sure that's particularly intuitive
or
useful, but again, it has no problem with string keys.Regards,
Rowan Collins
[IMSoP]
IMHO, stick to offsets in the first instance, this is a slice notation,
first order of business is to make it behave like array_slice (+on
strings). Assoc key based slicing feels pretty wrong to me at this point.
IMHO, stick to offsets in the first instance, this is a slice notation,
first order of business is to make it behave like array_slice (+on
strings). Assoc key based slicing feels pretty wrong to me at this point.
I have to agree, we are getting ahead of ourselves.
A quick summary of what this RFC should cover:
- Slicing an array or string based on the positional index.
Things for future RFC consideration:
- Slicing an array or string based on the key.
- Index -1 for last item of list.
Everybody agree that the only focus of this RFC should be the positional
index slicing?
Alex Bowers wrote on 20/03/2015 16:00:
IMHO, stick to offsets in the first instance, this is a slice notation, first order of business is to make it behave like array_slice (+on strings). Assoc key based slicing feels pretty wrong to me at this point.
I have to agree, we are getting ahead of ourselves.
A quick summary of what this RFC should cover:
- Slicing an array or string based on the positional index.
Things for future RFC consideration:
- Slicing an array or string based on the key.
- Index -1 for last item of list.
Everybody agree that the only focus of this RFC should be the
positional index slicing?
I'd be tempted to introduce the ability to get a single element by
position as well, just because that would be a really useful feature,
and "accessing array elements by their position" is kind of
pre-requisite for "accessing a set of array elements by their positions"
anyway. It might also make the rationale for the eventual syntax more
obvious to those who haven't been reading this conversation. :)
Regards,
Rowan Collins
[IMSoP]
I'd be tempted to introduce the ability to get a single element by
position as well
Absolutely agree.
Can we agree on a symbol do you think, or should the RFC continue for the
symbol discussion?
IMHO, stick to offsets in the first instance, this is a slice notation,
first order of business is to make it behave like array_slice (+on
strings). Assoc key based slicing feels pretty wrong to me at this point.I have to agree, we are getting ahead of ourselves.
A quick summary of what this RFC should cover:
- Slicing an array or string based on the positional index.
Things for future RFC consideration:
- Slicing an array or string based on the key.
- Index -1 for last item of list.
Everybody agree that the only focus of this RFC should be the positional
index slicing?
I think that's plenty for initial scope, since at this point proposals are
targeting 7.1 there's plenty of time to get assoc indexing in if there is
enough support for this in the first instance.
If there is support for positional but not assoc, we don't want this
proposal to fail on the fact they are bundled together.
Not sure I understand your index -1 line (sorry, on phone in pub, really
just skimming mails). If you mean negative indices for positions from the
end of the array/string then +1 for this with the slice syntax.
For $thing[-1] I think this only works for strings (and I have this
implemented, should probably RFC it)
https://github.com/lt/php-src/tree/string_negative_offset
$thing[-1:] is in scope for arrays though
I agree the scope is enough. Going with what Rowan added in about
individual indexes (not slicing) by position to be added in with this,
since the two go together.
In my opinion, the $thing[-1] should be a separate RFC, since it has little
to do with slicing, which is the primary focus of this RFC.
IMHO, stick to offsets in the first instance, this is a slice notation,
first order of business is to make it behave like array_slice (+on
strings). Assoc key based slicing feels pretty wrong to me at this point.I have to agree, we are getting ahead of ourselves.
A quick summary of what this RFC should cover:
- Slicing an array or string based on the positional index.
Things for future RFC consideration:
- Slicing an array or string based on the key.
- Index -1 for last item of list.
Everybody agree that the only focus of this RFC should be the positional
index slicing?I think that's plenty for initial scope, since at this point proposals are
targeting 7.1 there's plenty of time to get assoc indexing in if there is
enough support for this in the first instance.If there is support for positional but not assoc, we don't want this
proposal to fail on the fact they are bundled together.Not sure I understand your index -1 line (sorry, on phone in pub, really
just skimming mails). If you mean negative indices for positions from the
end of the array/string then +1 for this with the slice syntax.For $thing[-1] I think this only works for strings (and I have this
implemented, should probably RFC it)
https://github.com/lt/php-src/tree/string_negative_offset$thing[-1:] is in scope for arrays though
$thing[-1:] is in scope for arrays though
How would this work for slicing?
Since doing [@-1:] would mean get the last element to the end.
And doing [@1:-1] is the exact same as doing [@1:] since -1 and blank both
mean the end.
Leigh wrote on 20/03/2015 16:17:
For $thing[-1] I think this only works for strings (and I have this
implemented, should probably RFC it)
https://github.com/lt/php-src/tree/string_negative_offset$thing[-1:] is in scope for arrays though
Why? Getting the last value of an array is just as useful as getting the
last character of a string.
It doesn't work with that syntax, because -1 is a valid key, just as
$thing[0] can't mean "first value of array" because it already means
"value with key 0". That's why I propose a new syntax such as
$thing[@0], $thing[@-1], etc.
Regards,
Rowan Collins
[IMSoP]
That's why I propose a new syntax such as $thing[@0], $thing[@-1]
I have to agree that a new syntax will be required by this.
Leigh wrote on 20/03/2015 16:17:
For $thing[-1] I think this only works for strings (and I have this
implemented, should probably RFC it) https://github.com/lt/php-src/
tree/string_negative_offset$thing[-1:] is in scope for arrays though
Why? Getting the last value of an array is just as useful as getting the
last character of a string.It doesn't work with that syntax, because -1 is a valid key, just as
$thing[0] can't mean "first value of array" because it already means "value
with key 0". That's why I propose a new syntax such as $thing[@0],
$thing[@-1], etc.Regards,
Rowan Collins
[IMSoP]
Is everybody happy with the RFC being called 'Slice Operator', or is there
a better name for it?
Leigh wrote on 20/03/2015 16:17:
For $thing[-1] I think this only works for strings (and I have this
implemented, should probably RFC it) https://github.com/lt/php-src/
tree/string_negative_offset$thing[-1:] is in scope for arrays though
Why? Getting the last value of an array is just as useful as getting the
last character of a string.It doesn't work with that syntax, because -1 is a valid key, just as
$thing[0] can't mean "first value of array" because it already means "value
with key 0". That's why I propose a new syntax such as $thing[@0],
$thing[@-1], etc.Regards,
Rowan Collins
[IMSoP]
It doesn't work with that syntax, because -1 is a valid key, just as $thing[0] can't mean "first value of array" because it already means "value with key 0". That's why I propose a new syntax such as $thing[@0], $thing[@-1], etc.
I would just like to point out that the @ error suppression operator operates on expressions. Unfortunately, that means that also using @ as a slice operator makes the two ambiguous with each other in those contexts. The concept itself can still work, but it’d need a token other than @.
-John
The concept itself can still work, but it’d need a token other than @.
This is the symbol currently being used for examples, but thats all it is
currently. Nothing is set in stone (and most likely will change), not just
for this reason but for the reason that I mentioned earlier in the thread
that the @ symbol has bad connotations, and avoiding these connotations
would benefit the RFC.
I posted four suggestions earlier,
They were:
@
&
^
My favourites are the asterisk or caret.
Hi!
My proposal is something similar to Pythons slice, in PHP this would look
like:$slided = $array[1:4]
This will get the elements in positions 1,2,3,4. (1 through 4 inclusive),
ignoring the actual key of the array. The result for an array will be an
array with the keys preserved, in the same order.
I'm not sure how such operation would be useful, and it definitely would
not be intuitive, as $array[0] and $array[0:1] (assuming non-inclusive
semantic, or [0:0] with inclusive semantics) would return completely
different things. That would happen even if the array has only numeric
keys! This is the main problem with this syntax - unlike most languages
where it is used, PHP arrays are not vectors, they are ordered hashmaps.
Sometimes this is very convenient, sometimes - like for this syntax - it
is not. I think this is the major reason why such proposals failed in
the past.
--
Stas Malyshev
smalyshev@gmail.com
Hi!
My proposal is something similar to Pythons slice, in PHP this would look
like:$slided = $array[1:4]
This will get the elements in positions 1,2,3,4. (1 through 4 inclusive),
ignoring the actual key of the array. The result for an array will be an
array with the keys preserved, in the same order.I'm not sure how such operation would be useful, and it definitely would
not be intuitive, as $array[0] and $array[0:1] (assuming non-inclusive
semantic, or [0:0] with inclusive semantics) would return completely
different things. That would happen even if the array has only numeric
keys! This is the main problem with this syntax - unlike most languages
where it is used, PHP arrays are not vectors, they are ordered hashmaps.
Sometimes this is very convenient, sometimes - like for this syntax - it
is not. I think this is the major reason why such proposals failed in
the past.
My interest in this proposal is mostly because it can potentially provide a convenient way to get the first element in an array, which is a not-infrequent need of mine.
I provided an array_key_first() implementation awhile ago that was first shot down because “too many array_* functions”, and then later ignored because I didn’t want to go through the RFC process just to add a few functions. (PR here: https://github.com/php/php-src/pull/347)
If people are generally interested in having an array_key_(first|last|index) implementation, I can dust off that PR, update it for master, and if we really need an RFC, I’ll prepare one for PHP 7.1.
-John
If people are generally interested in having an array_key_(first|last|index) implementation, I can dust off that PR, update it for master, and if we really need an RFC, I’ll prepare one for PHP 7.1.
-John
I’d be very interested in this, though I don’t have voting karma.
The latest comments in this thread are talking about having a symbol before
the range to show that it is by positional index. Current propositions for
this are ^ and *.
I'm not sure how such operation would be useful
Anywhere on the front-end where a foreach() is used, and expects at most
say, 10 items. But the full dataset is fetched back (to show a summary
after the first 10 or whatever other reason).
The old code would have required a counter, the new code does not. This
would make it cleaner for the front-end developer to understand.
<?php
$results = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
// Old
$count = 0;
foreach($results as $result){
if($count++ > 9) break;
echo $result . "\n"; // 1 2 3 4 5 6 7 8 9
}
// New
foreach($results[*:9] as $result) {
echo $result . "\n"; // 1 2 3 4 5 6 7 8 9
}
$string = "abcdefghijklmnop";
// Old
echo substr($string, 0, 5); // abcde
// New
echo $string[*:4]; // abcdef
This is just a few basic examples, but should show that there is a use case
for it.
Hi!
My proposal is something similar to Pythons slice, in PHP this would
look
like:$slided = $array[1:4]
This will get the elements in positions 1,2,3,4. (1 through 4
inclusive),
ignoring the actual key of the array. The result for an array will be an
array with the keys preserved, in the same order.I'm not sure how such operation would be useful, and it definitely would
not be intuitive, as $array[0] and $array[0:1] (assuming non-inclusive
semantic, or [0:0] with inclusive semantics) would return completely
different things. That would happen even if the array has only numeric
keys! This is the main problem with this syntax - unlike most languages
where it is used, PHP arrays are not vectors, they are ordered hashmaps.
Sometimes this is very convenient, sometimes - like for this syntax - it
is not. I think this is the major reason why such proposals failed in
the past.--
Stas Malyshev
smalyshev@gmail.com
Alex Bowers wrote:
Anywhere on the front-end where a foreach() is used, and expects at most
say, 10 items. But the full dataset is fetched back (to show a summary
after the first 10 or whatever other reason).The old code would have required a counter, the new code does not. This
would make it cleaner for the front-end developer to understand.<?php
$results = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];// Old
$count = 0;foreach($results as $result){
if($count++ > 9) break;
echo $result . "\n"; // 1 2 3 4 5 6 7 8 9
}// New
foreach($results[*:9] as $result) {
echo $result . "\n"; // 1 2 3 4 5 6 7 8 9
}
// alternative old
foreach(array_slice($results, 0, 9) as $result) {
echo $result . "\n"; // 1 2 3 4 5 6 7 8 9
}
Not so bad, in my opinion.
--
Christoph M. Becker
// alternative old
foreach(array_slice($results, 0, 9) as $result) {
echo $result . "\n"; // 1 2 3 4 5 6 7 8 9
}
Not so bad, in my opinion.
To be the same, your example would have to be:
// alternative old
foreach(array_slice($results, 0, 9, true) as $result) {
echo $result . "\n"; // 1 2 3 4 5 6 7 8 9
}
since this will preserve the array keys.
This was a quick off the top of my head example; there is also the benefit
of overwriting multiple array items with a single line
$array[*1:4] = [1,2,3,4]; // Sets array items 1 through 4 to be the values
(and keys if provided), of the array assigned.
$array[*1:] = [1,2,3,4]; // Sets array items 1 to the end to be values (and
keys if provided), of the array assigned. This will also wipe out any
additional information to the end of the array. Keeping anything before the
first item, but extending until the end.
This would be similar to array_replace, however that works from keys, not
positions.
Hi!
To be the same, your example would have to be:
// alternative old
foreach(array_slice($results, 0, 9, true) as $result) {
echo $result . "\n"; // 1 2 3 4 5 6 7 8 9
}since this will preserve the array keys.
You're not using the keys in foreach, so why you need to preserve them?
$array[*1:4] = [1,2,3,4]; // Sets array items 1 through 4 to be the
values (and keys if provided), of the array assigned.
This may be not so easy to implement - imagine passing $array[*1:4] by
reference. You should be able to do so, since $array[*1:4] is an lvalue
for you, but what would you pass? What if $array changes in the
meantime? There's a big can of worms here. And you already have
array_splice which doesn't have these issues.
--
Stas Malyshev
smalyshev@gmail.com
You're not using the keys in foreach, so why you need to preserve them?
This was merely an example of the features equal part in current code, not
a real life use case.
Using the new syntax will keep the keys preserved, therefore any example
showing how to do the same must do the same, which preserving keys does.
This may be not so easy to implement - imagine passing $array[*1:4] by
reference.
This would be the same as doing
$array[array_keys($old_array)[1]] = $new_array[0];
$array[array_keys($old_array)[2]] = $new_array[1];
$array[array_keys($old_array)[3]] = $new_array[2];
$array[array_keys($old_array)[4]] = $new_array[3];
The new syntax helps clean that up, by doing:
$array[*1:4] = [1,2,3,4];
There is nothing to pass by reference that is different, the array is still
$array, it is just having the values replaced in bulk by index (not by key)
This sort of code would be needed:
<?php
$old_array = [0 => 1, 1 => 2, 5 => 3, 7 => 4, 4 => 5, 2 => 6, 14 => 7, 55
=> 8];
$new_array_values = ['foo', 'bar', 'baz'];
// To replace the third, fourth and fifth element.
$old_array[array_keys($old_array)[3]] = $new_array_values[0];
$old_array[array_keys($old_array)[4]] = $new_array_values[1];
$old_array[array_keys($old_array)[5]] = $new_array_values[2];
var_dump($old_array);
Instead of, what is in my opinion, much cleaner:
<?php
$old_array = [0 => 1, 1 => 2, 5 => 3, 7 => 4, 4 => 5, 2 => 6, 14 => 7, 55
=> 8];
$new_array_values = ['foo', 'bar', 'baz'];
$old_array[*3:5] = $new_array_values;
var_dump($old_array);
There is the array_splice method that can do the same thing, however this
to me is less obvious as to what is happening:
<?php
$old_array = [0 => 1, 1 => 2, 5 => 3, 7 => 4, 4 => 5, 2 => 6, 14 => 7, 55
=> 8];
$new_array_values = ['foo', 'bar', 'baz'];
// To replace the third, fourth and fifth element.
array_splice($old_array, 3, 3, $new_array_values);
var_dump($old_array);
Hi!
This may be not so easy to implement - imagine passing $array[*1:4] by reference.
This would be the same as doing
$array[array_keys($old_array)[1]] = $new_array[0];
$array[array_keys($old_array)[2]] = $new_array[1];
$array[array_keys($old_array)[3]] = $new_array[2];
$array[array_keys($old_array)[4]] = $new_array[3];
I don't think you understood what I am saying. Lvalues in PHP can be
used not only in assignment context, but also in passing-by-ref context,
and in that case I have no idea how you pass $array[*1:4] by reference -
what is actually passed?
There is the array_splice method that can do the same thing, however
this to me is less obvious as to what is happening:
I don't see any reason why it would be less obvious, if you bother to
look at man page of array_splice once.
--
Stas Malyshev
smalyshev@gmail.com
$array[*1:4] by reference -
what is actually passed?
Implementation is not something I have looked into for this yet, so I am
unsure how this would be possible; but by passing $array[*1:4], you'd be
passing an extracted array which is a reference to the original array. Such
that changing the sub array can change the parent array.
Hi!
Implementation is not something I have looked into for this yet, so I am
unsure how this would be possible; but by passing $array[*1:4], you'd be
passing an extracted array which is a reference to the original array.
Such that changing the sub array can change the parent array.
Exactly. This means you can not make $array[*1:4] a real lvalue, which
means you instead need to make it some kind of a hack on case-by-case
basis, at which point it's no better than array_splice only implemented
in more complicated way.
--
Stas Malyshev
smalyshev@gmail.com
Would it make more sense then to have a RFC for array by positional index.
No range or anything initially (that will be a separate RFC), but simply to
get the value of an array by positional index?
$array[*4] to get the item in position 4.
I'm not sure how such operation would be useful, and it definitely would
not be intuitive, as $array[0] and $array[0:1] (assuming non-inclusive
semantic, or [0:0] with inclusive semantics) would return completely
different things. That would happen even if the array has only numeric
keys! This is the main problem with this syntax - unlike most languages
where it is used, PHP arrays are not vectors, they are ordered hashmaps.
Sometimes this is very convenient, sometimes - like for this syntax - it
is not. I think this is the major reason why such proposals failed in
the past.
It would give different results, for a reason. There is currently no way to
get an array item by positional index, whilst preserving the keys.
This RFC will allow that, with the inclusion of the symbol that will be
required for this RFC (slicing by key can be a separate RFC; and is not
covered by this RFC).
So, if i want to get the items from position 1 through 5, I can use [*1:5]
and I will get an array of the items in position 1,2,3,4 and 5; regardless
of their keys, as an array.
Hi!
It would give different results, for a reason. There is currently no way
to get an array item by positional index, whilst preserving the keys.
I imagine having such way may be useful. However, reusing array access
syntax for that does not look like a good idea, since it would look like
existing array syntax but work completely different. Why not use
array_slice for it?
Stas Malyshev
smalyshev@gmail.com
Why not use array_slice for it?
There certainly are ways to do most of what this RFC covers, however most
of them don't lend themselves well to clean code in my opinion.
Thats why this RFC is listed as being syntactic sugar.
Hi!
It would give different results, for a reason. There is currently no way
to get an array item by positional index, whilst preserving the keys.I imagine having such way may be useful. However, reusing array access
syntax for that does not look like a good idea, since it would look like
existing array syntax but work completely different. Why not use
array_slice for it?Stas Malyshev
smalyshev@gmail.com
Hi!
There certainly are ways to do most of what this RFC covers, however
most of them don't lend themselves well to clean code in my opinion.
I must disagree with the notion that "clean code" can only include
operators and not functions. There's nothing wrong with using functions.
--
Stas Malyshev
smalyshev@gmail.com