> That said, another possibility I thought of is automatically converting whatever is passed into a foreach loop to > be cast into an iterable/array for the duration of the loop. I'm wondering what opinions would be on the cons of > going this route. Given php's weak typing and someone's desire to execute a foreach on _something_, I think > this alternate method might be a good option.
PHP kinda already does this. It won't do it for all types (e.g. each string of a letter), but it'll implicitly cast any object to property => value pairs for all publically accessible properties if the object hasn't defined its own way of being traversable. e.g. ``` $O = new class() { private $a = '1'; protected $b = '2'; public $c = '3'; }; foreach ($O as $k => $v) { echo "$k: $v"; } ``` Will output: ``` c: 3 ``` Kind regards, Aidan On 12 July 2017 at 18:25, Mark Shust <m...@shust.com> wrote: > I agree, error suppression is generally ugly/nasty behavior that is a hack > to the language. I also agree that if it's there now, @as is a pretty good > use for it. > > That said, another possibility I thought of is automatically converting > whatever is passed into a foreach loop to be cast into an iterable/array > for the duration of the loop. I'm wondering what opinions would be on the > cons of going this route. Given php's weak typing and someone's desire to > execute a foreach on _something_, I think this alternate method might be a > good option. > > Mark > > > On Wed, Jul 12, 2017 at 12:18 PM Aidan Woods <aidantwo...@gmail.com> > wrote: > >> > IMHO the whole error supression and its operator should be deprecated >> and removed from language. >> > Supressing errors is just hiding problems because someone didn't want >> to solve it. Supressing errors >> > makes debuging very hard and leads to frustration. >> >> I can concur with disliking the error suppression operator, and in >> general silent failures. This is why we >> have linting CI checkers though ;-) Tbh, I also dislike silent type >> "juggling" for the same reason. But >> those are my opinions, and they don't get on with everyone. >> >> Deprecation of the operator is probably a different discussion. Though to >> say a few words on it: if >> presented with no other option, I'd rather someone suppress an error in a >> controlled single-use >> manner, than changing the global error reporting setting somewhere in >> their code to do the same >> thing. >> Notwithstanding my preference on error suppression method, I'd >> still prefer it avoided if at all possible, >> though again, very much IMO. >> >> Regardless of personal opinion on actually using the operator, would you >> not rather it were used in all >> cases of error suppression? >> 'tis to say, if we are going to introduce new error suppression behaviour >> (which is what the proposal >> here does), should it not be consistent with existing language features? >> >> Given that the error suppression operator is a feature already in the >> language, I think that it makes >> sense to use it to facilitate this use case of "silently skip the loop >> if it errors", as opposed to introducing >> a new operator to do it. >> >> I think it makes sense to force its use to be as targeted as possible too: >> Placing the `@` on `as` is the most targeted placement for catching the >> failure we're talking about (failing to >> be able to iterate over something), as opposed to something like >> `@foreach` which could feasibly mean >> anything failing in the entire loop block. >> >> If we're going to introduce this behaviour, let's get it right ;-) (even >> if we don't like it ourselves) >> >> Kind regards, >> Aidan >> >> On 12 July 2017 at 16:26, Michał Brzuchalski < >> michal.brzuchal...@gmail.com> wrote: >> >>> 12.07.2017 15:35 "Mark Shust" <m...@shust.com> napisał(a): >>> > >>> > Hi Aidan, >>> > >>> > I think you are correct on all points. The initial emit is just a >>> warning, >>> > so I think a suppressor will work just fine, since it does just pass >>> over >>> > the foreach if a traversable isn't passed in. >>> > >>> > I could see this being helpful as it makes wrapping an if block around >>> a >>> > foreach not needed anymore (and in turn indenting the foreach another >>> > level), replacing it with just a single character. I also think for >>> those >>> > that use linting tools and flag error suppressions, that an @as >>> definition >>> > could be easily ignored from such a linter. I develop with warnings >>> on, and >>> > see error suppressions as a sort of code smell, however I think the @as >>> > definition could be really useful. >>> >>> IMHO the whole error supression and its operator should be deprecated >>> and removed from language. Supressing errors is just hiding problems >>> because someone didn't want to solve it. Supressing errors makes debuging >>> very hard and leads to frustration. >>> >>> > >>> > Cheers, >>> > Mark >>> > >>> > On Wed, Jul 12, 2017 at 4:22 AM Aidan Woods <aidantwo...@gmail.com> >>> wrote: >>> > >>> > > In theory you'd only *need* it be considered a suppressor? PHP >>> already >>> >>> > > exhibits the skipping behaviour (it only emits a warning for the >>> wrong type >>> > > used in `foreach`, skips the loop, and then continues with remaining >>> code). >>> > > >>> > > No harm in/there is probably value in, making that skipping intent >>> > > explicit in a RFC though, but in terms of a patch, the warning would >>> only >>> > > need be suppressed as far as I can tell? >>> > > >>> > > Another thing I meant to mention -- this should not only be useful >>> for >>> > > arrays, but for any `Traversable` too (i.e. it should suppress errors >>> > > generated in using a type not compatible with being iterated over in >>> a >>> > > `foreach` loop, and not just if the type is not array). >>> > > >>> > > Kind regards, >>> > > Aidan >>> > > >>> > > On 12 July 2017 at 02:50, Mark Shust <m...@shust.com> wrote: >>> > > >>> > >> Aidan, >>> > >> >>> > >> Fantastic suggestion (@as) -- that is really the succinctness I was >>> > >> initially looking for, and I think the intention makes a lot of >>> sense. My >>> > >> only concern/issue would be to make sure that isn't considered a >>> > >> 'suppressor' -- but it's actual intent is to skip the execution of >>> the >>> > >> foreach to prevent the error/loop from occurring (rather than just >>> > >> suppressing an error). >>> > >> >>> > >> Cheers, >>> > >> Mark >>> > >> >>> > >> >>> > >> On Tue, Jul 11, 2017 at 4:05 PM Aidan Woods <aidantwo...@gmail.com> >>> > >> wrote: >>> > >> >>> > >>> If you were willing to accept >>> > >>> >>> > >>> ``` >>> > >>> foreach ($foo as $bar) if (is_array) { >>> > >>> ... >>> > >>> } >>> > >>> ``` >>> > >>> >>> > >>> as a solution, then you might as well use >>> > >>> >>> > >>> ``` >>> > >>> if (is_array($foo)) foreach ($foo as $bar) { >>> > >>> ... >>> > >>> } >>> > >>> ``` >>> > >>> >>> > >>> I wonder if this could be better achieved by expanding what the >>> error >>> > >>> suppression operator `@` can do? This entire behaviour seems more >>> like an >>> > >>> error suppression action on `foreach` to me, otherwise should we >>> consider >>> > >>> coalescing operators for other types/creating a more generic one? >>> > >>> >>> > >>> Going back to the error suppression operator: >>> > >>> >>> > >>> e.g. perhaps >>> > >>> >>> > >>> ``` >>> > >>> foreach ($foo @as $bar) { >>> > >>> ... >>> > >>> } >>> > >>> ``` >>> > >>> >>> > >>> could prevent skip past execution of the entire foreach block if >>> there >>> > >>> is an error using $foo as an array. So might make most sense to >>> place the >>> > >>> `@` on `as`, IMO, but I guess arguments could be made to place it >>> like >>> > >>> `@foreach ($foo as $bar)` or `foreach @($foo as $bar)`. >>> > >>> >>> > >>> >>> > >>> Regards, >>> > >>> Aidan >>> > >>> >>> > >>> On 11 July 2017 at 20:06, Mark Shust <m...@shust.com> wrote: >>> > >>> >>> > >>>> Thanks for the great feedback. >>> > >>>> >>> > >>>> Based on the last mindset on keyword syntax, this comes to mind, >>> > >>>> intended >>> > >>>> to be used similarly to the 'use' keyword when used within the >>> context >>> > >>>> of a >>> > >>>> closure: >>> > >>>> >>> > >>>> foreach ($foo as $bar) if (is_array) { >>> > >>>> ... >>> > >>>> } >>> > >>>> >>> > >>>> >>> > >>>> I don't think this is a vast improvement over wrapping this >>> within an >>> > >>>> is_array check, however it does avoid the additional >>> nest/wrapping. I >>> > >>>> was >>> > >>>> hoping for something that reads a bit more concisely or with a >>> bit more >>> > >>>> syntactical sugar than the above. I think this does read nicely >>> though. >>> > >>>> >>> > >>>> Cheers, >>> > >>>> Mark >>> > >>>> >>> > >>>> On Tue, Jul 11, 2017 at 1:50 PM Rowan Collins < >>> rowan.coll...@gmail.com> >>> > >>>> wrote: >>> > >>>> >>> > >>>> > On 11 July 2017 16:02:18 BST, Mark Shust <m...@shust.com> >>> wrote: >>> > >>>> > >For a syntactic >>> > >>>> > >sugar/improvement, this can be shorthand for executing the loop >>> > >>>> instead >>> > >>>> > >of >>> > >>>> > >wrapping the block within an is_array check: >>> > >>>> > > >>> > >>>> > > >>> > >>>> > ><?php >>> > >>>> > > >>> > >>>> > >$foo = "abc"; >>> > >>>> > > >>> > >>>> > >foreach (??$foo as $bar) { >>> > >>>> > > >>> > >>>> > > echo $bar; >>> > >>>> > > >>> > >>>> > >} >>> > >>>> > >>> > >>>> > Hi! >>> > >>>> > >>> > >>>> > I think there's definitely the start of a good idea here, but >>> the >>> > >>>> syntax >>> > >>>> > you suggest doesn't read quite right. As has been pointed out, >>> this >>> > >>>> differs >>> > >>>> > from existing features in two ways: >>> > >>>> > >>> > >>>> > - the special handling is for any non-iterable value, not just >>> null or >>> > >>>> > empty/falsey values, for which you could use $foo??[] and >>> $foo?:[] >>> > >>>> > respectively >>> > >>>> > - the handling is to skip the loop, not loop once assigning >>> $bar to >>> > >>>> the >>> > >>>> > scalar value, as would happen with (array)$foo >>> > >>>> > >>> > >>>> > The challenge, then, is to come up with some syntax that somehow >>> > >>>> suggests >>> > >>>> > these rules. The "??" is too much like the null coalesce, which >>> would >>> > >>>> be >>> > >>>> > misleading. >>> > >>>> > >>> > >>>> > The only idea that immediately comes to mind is a keyword: >>> > >>>> > >>> > >>>> > foreach ifarray ($foo as $bar) { >>> > >>>> > >>> > >>>> > I can't say I'm that keen on that syntax, but maybe it will >>> inspire >>> > >>>> > someone else. >>> > >>>> > >>> > >>>> > Regards, >>> > >>>> > >>> > >>>> > -- >>> > >>>> > Rowan Collins >>> > >>>> > [IMSoP] >>> > >>>> > >>> > >>>> >>> > >>> >>> > >>> >>> > > >>> >>> >>