I'm using PHP's foreach(), Sometimes when the inner code doesn't do what i want, I'd like to re-try the same level instead of continuing to the next one.
Is that possible?
Example:
foreach($pics AS $pic){
if(!upload($pic)){
again; // something like this
}
}
No but you can put a while loop inside your loop, this has equivalent behaviour as what you desire above. However you should modify it to use a counter and stop after X many retries to prevent infinite looping.
foreach($pics AS $pic){
while(!upload($pic));
}
You will need to surround your if with another loop which loops a certain number of times (your maximum retry count), or until you manually break out of it when your code succeeds.
You could use a goto I suppose, but that is generally frowned upon, and would do the same thing as an inner loop anyway.
function dosomething() {
foreach($pics AS $pic){
if(!upload($pic)){
break;
}
}
$success = true;
}
$success=false;
while( !$success ) dosomething();
While this in theory should work.
I would say absolutely bad programming practice, as you have a good chance of a never ending loop.
Related
I have to maintain a code, and came up with this:
for (;;) {
//code
}
What would it do? I couldn't find documentation about it.
In a hunch I think it runs only once... but that would be useless...
it is an infinite loop, similar in function as:
while(true)
{
}
Your code sample is an infinite loop. To terminate, the omitted code (//code) must exit the loop or the entire PHP script.
It's a for loop without initialization parameters, no breaking conditions and no increments/decrements/whatever on each iteration - think of it like for (nothing; nothing; nothing).
Unless you break it from the inside, it's going to run forever.
For embedded code it is the main loop that does all the other sub process in a super loop scheme.
I was looking through some code at work and found something I've not encountered before:
for (; ;)
{
// Some code here
break;
}
We call the function that contains this all the time, I only recently got in there to see how it works. Why does this work and is it documented somewhere?
It seems as though a while loop would have been more appropriate in this instance...
It's essentially the same as while(true). It doesn't have any initialisation, doesn't change anything between iterations, and in the absence of anything to make it false the condition is assumed to be true.
It's an infinite loop.
Normally you would have something like:
for ($i=0; $i<10; $i=$i+1)
But you can omit any of the parts.
These are all valid:
for ($i=0; ; $i=$i+1)
for (; $i<10; $i=$i+1)
for (; $i<10;)
However, if you omit the second part, there will be no condition for exiting the loop. This can be used if you do not know how many times you want to run the loop. You can use a break instruction to exit the loop in that case
for (;;)
{
// some code
if (some condition)
break;
}
Note that if you do not put a break the page will just get stuck and run indefinitely
The first blank statement is executed at the beginning.
The second blank expression (which determines whether you exit the loop or not) evaluates to TRUE implicitly:
http://php.net/manual/en/control-structures.for.php
The third blank statement executes after each iteration.
So any condition that kicks out of the loop will need to be in the loop itself.
As you all probably know, do loops execute at least once, even if the statement is false — while the while loop would never execute even once if the statement is false.
When are do loops useful? Could someone give me a real life example?
They're basically useful when you want something to happen at least once, and maybe more.
The first example that comes to mind is generating a unique ID (non sequentially) in a database. The approach I sometimes take is:
lock table
do {
id = generate random id
} while(id exists)
insert into db with the generated id
unlock table
Basically it will keep generating ids until one doesn't exist (note: potentially an infinite loop, which I might guard against depending on the situation).
The Do loop is very powerfull if you have to check multiple files etc. Due to the guarentee of iteration it will work all the way through.
do {
if($integer > 0) { $nameoffile[0]++; }
else { $nameoffile[0] = $nameoffile[0].$integer; }
$integer++;
} while(file_exists("directory/".$nameoffile[0].".".$nameoffile[1]));
Next to what has already been answered, you can do crude stuff like this with a do:
do
{
if ($cond1) break;
if ($cond2) continue;
do_something();
} while(true/false);
Which is a modification of a switch loop, which allows continue. You can simulate goto similarities in case goto is not available and similar.
It must not make your code more readable, so it's often not suggested to do that. But it technically works.
I'm reading an ebook on PHP right now, and the author noted that the difference between a while loop and a for loop is that the for loop will count how many times it runs.
So take this:
<?php
for ($i = 1; $i < 10; $i = $i + 1) {
print "Number $i\n";
}
?>
But wouldn't this be the same as
<?php
$i = 1;
while ($i < 10) {
$i = $i + 1;
print "Number $i\n";
}
?>
Or is there some other differences that he didn't point out? (Aside from using while loop for when you're unsure of how long the condition will remain true, such as selecting rows from a database)
I mean, if that's the only difference, can't I just not use the for loop and use the while loop instead?
"For" expresses your intentions more clearly
Functionally, your two examples are the same. But they express different intentions.
while means 'I don't know how long this condition will last, but as long as it does, do this thing.'
for means 'I have a specific number of repetitions for you to execute.'
You can use one when you mean the other, but it's harder to read the code.
Some other reasons why for is preferable here
It's more concise and puts all the information about the loop in one place
It makes $i a local variable for the loop
Don't forget foreach
Personally, the loop I use most often in PHP is foreach. If you find yourself doing things like this:
for ($i=0; $i < count($some_array); $i++){
echo $some_array[$i];
}
...then try this:
foreach ($some_array as $item){
echo $item;
}
Faster to type, easier to read.
Can you? Yes, certainly. But whether or not you should is an entirely different question.
The for loop is more readable in this scenario, and is definitely the convention you'll find used within virtually every language that has looping directives. If you use the while loop, people are going to wonder why you didn't use a for loop.
Functionally, a for loop is equivalent to a while loop; that is, each can be rewritten as the other with no change to the outcome or side effects. However, each has different connotations. A while loop runs while a condition holds; the condition is static, though circumstances change. A for loop runs over a sequence. The difference is important to programmers but not programs, just as choice of variables names are important to programmers even though they can be changed to produce functionally equivalent code. One loop construct will make more sense than the other, depending on the situation.
A for-loop
for (INIT; CONDITIONS; UPDATE) {
BODY
}
is basically the same as a while-loop structured like this:
INIT
while (CONDITIONS) {
BODY
UPDATE
}
While you could technically use one or the other, there are situations where while works better than for and vice-versa.
The Main Difference Between for() and While() is that we have to define the limit or count but in while() loop we don't define limit or count it works until reached the last item
FOR LOOP
Initialization may be either in loop statement or outside the loop.
It is normally used when the number of iterations is known.
Condition is a relational expression.
It is used when initialization and increment is simple.
for ( init ; condition ; iteration )
{ statement(s); }
WHILE LOOP
Initialization is always outside the loop.
It is normally used when the number of iterations is unknown.
Condition may be expression or non-zero value.
It is used for complex initialization.
while ( condition )
{ statement(s); }
It's a matter of taste, personal preference and readability. Sometimes a while loop works better logically. Sometimes, a for.
For my personal rule, if I don't need a variable initializer, then I use a while.
But a foreach loop is useful in its own way.
Plus, in the case of PHP's scoping, where all variables not inside of functions are global, it the variable will continue living after the loop no matter which loop control you use.
I feel dirty every time I "break" out of a for-each construct (PHP/Javascript)
So something like this:
// Javascript example
for (object in objectList)
{
if (object.test == true)
{
//do some process on object
break;
}
}
For large objectLists I would go through the hassle building a more elegant solution. But for small lists there is no noticeable performance issue and hence "why not?" It's quick and more importantly easy to understand and follow.
But it just "feels wrong". Kind of like a goto statement.
How do you handle this kind of situation?
I use a break. It's a perfectly cromulent solution.
It's quick and more importantly easy to understand and follow.
Don't feel bad about break. Goto is frowned upon because it's quick and more importantly not easy to understand and follow.
See, the break doesn't bug me at all. Programming is built on goto, and for-break - like all control structures - is merely a special-purpose form of goto meant to improve the readability of your code. Don't ever feel bad about writing readable code!
Now, I do feel dirty about direct comparisons to true, especially when using the type-converting equality operator... Oh yeah. What you've written - if (object.test == true) - is equivalent to writing if (object.test), but requires more thought. If you really want that comparison to only succeed if object.test is both a boolean value and true, then you'd use the strict equality operator (===)... Otherwise, skip it.
For small lists, there's no issue with doing this.
As you mention, you may want to think about a more 'elegant' solution for large lists (especially lists with unknown sizes).
Sometimes it feels wrong, but it's all right. You'll learn to love break in time.
Like you said ""why not?" It's quick and more importantly easy to understand and follow."
Why feel dirty, I see nothing wrong with this.
I think is is easier to read and hence easier to maintain.
It is meant to be like it. Break is designed to jump out of a loop. If you have found what you need in a loop why keep the loop going?
Breaks and continues are not gotos. They are there for a reason. As soon as you're done with a loop structure, get out of the loop.
Now, what I would avoid is very, very deep nesting (a.k.a. the arrowhead design anti-pattern).
if (someCondition)
{
for (thing in collection)
{
if (someOtherCondition)
{
break;
}
}
}
If you are going to do a break, then make sure that you've structure your code so that it's only ever one level deep. Use function calls to keep the iteration as shallow as possible.
if (someCondition)
{
loopThroughCollection(collection);
}
function loopThroughCollection(collection)
{
for (thing in collection)
{
if (someOtherCondition)
{
doSomethingToObject(thing);
break;
}
}
}
function doSomethingToObject(thing)
{
// etc.
}
I really don't see anythign wrong with breaking out of a for loop. Unless you have some sort of hash table, dictionary where you have some sort of key to obtain a value there really is no other way.
I'd use a break statement.
In general there is nothing wrong with the break statement. However your code can become a problem if blocks like these appear in different places of your code base. In this case the break statements are code small for duplicated code.
You can easily extract the search into a reusable function:
function findFirst(objectList, test)
{
for (var key in objectList) {
var value = objectList[key];
if (test(value)) return value;
}
return null;
}
var first = findFirst(objectList, function(object) {
return object.test == true;
}
if (first) {
//do some process on object
}
If you always process the found element in some way you can simplify your code further:
function processFirstMatch(objectList, test, processor) {
var first = findFirst(objectList, test);
if (first) processor(first);
}
processFirst(
objectList,
function(object) {
return object.test == true;
},
function(object) {
//do some process on object
}
}
So you can use the power of the functional features in JavaScript to make your original code much more expressive. As a side effect this will push the break statement out of your regular code base into a helper function.
Perhaps I'm misunderstanding your use-case, but why break at all? I'm assuming you're expecting the test to be true for at most one element in the list?
If there's no performance issue and you want to clean up the code you could always skip the test and the break.
for (object in objectList)
{
//do some process on object
}
That way if you do need to do the process on more than one element your code won't break (pun intended).
Use a
Object object;
int index = 0;
do
{
object = objectList[index];
index++;
}
while (object.test == false)
if breaking from a for loop makes you feel uneasy.
My preference is to simply use a break. It's quick and typically doesn't complicate things.
If you use a for, while, or do while loop, you can use a variable to determine whether or not to continue:
for ($i = 0, $c = true; ($i < 10) && $c; $i++) {
// do stuff
if ($condition) {
$c= false;
}
}
The only way to break from a foreach loop is to break or return.