Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

What's the difference between scan for and scan while...? 7

Mandy_crw

Programmer
Jul 23, 2020
580
PH
Hi everyone...i have been using these two... scan for and scan while... and it works perfectly may you help me explain further how these two works so that i could use the most appropriate scan basing on my needs... Thanks in advance....
 
Scan for will process a whole table start to finish excluding the records that do not match the for clause, like a filter.

Scan while starts from where the the current record pointer is, and stops when the while clause is no longer valid.

So for scan while, you position (typically) using a seek to get the first match, then process the next x records that work
with the clause and then stop.
 
I *think* scan while may not be at eof() on completion, while scan for will be (tested, that is right)
 
Scan for will process a whole table start to finish excluding the records that do not match the for clause, like a filter.

Scan while starts from where the the current record pointer is, and stops when the while clause is no longer valid.

So for scan while, you position (typically) using a seek to get the first match, then process the next x records that work
with the clause and then stop.
Oh I see... Thanks Griff...
 
A little experiment shows that
Code:
Create Cursor test (id int)
For i = 1 to 10
   Append Blank
EndFor
Go 2
Scan While Recno()<5
   ? Recno()
EndScan
? Recno(), Eof()
First important difference of Scan and Scan While is that Scan causes a "go top", whereas Scan While (and also Scan Rest) starts at the current record.

The while condition is checked and if it is met, the loop body is executed, at Endscan the recordpointer increses, which means after endscan you end at a record not fulfilling the while condition anymore, i.e. when after increasing the record pointer the record is not fulfilling the while condition, the loop ends and you're at that record.
So you neither end at the last record that was in the loop nor (generally) at EOF(). You can end at EOF(), if all records fulfill the while condition, then the loop obviously still has to end at the end of the cursor, at EOF().

It's good to know that Endscan and not Scan increases the record pointer, that's generally true, for whatever Scan, Scan Rest, Scan For, Scan While.
 
Last edited:
There's also an important difference to Scan For:

While is literally while, that means in data like the following a condition FOR field2=2 would mean all records with field2=2 in rows 1,2,3 and 5, but a While would stop at row 4, even though there's one more row with field2=2 next row. It's literally only processing record by record WHILE a condition is true, not FOR all records that fulfill the condition.

Code:
Create Cursor test (id int, field2 int)
For i = 1 to 10
   insert into test values (i,1)
EndFor
Replace field2 with 2 For inlist(Recno(),1,2,3,5)
Go top
? 'while'
Scan While field2=2
   ? Recno()
EndScan
? 'for'
Scan for field2=2
   ? Recno()
EndScan
You can also (indirectly) learn from the last loop that a Scan For automatically starts with the first record fulfilling the For condition. It automatically positions/guides the record pointer to all records fulfilling the FOR condition. That compares to WHERE in SQL, whereas WHILE has no equivalent in (simple) SQL.

That's also sometimes the tricky thing of while, you have to remember you first have to position on a record fulfilling the while condition, the loop doesn't guide the record pointer to the first record fulfilling that condition, if the while condition isn't met by the current record, the loop doesn't even work once and instead immediately ends.
 
Last edited:
Hi everyone...i have been using these two... scan for and scan while... and it works perfectly may you help me explain further how these two works so that i could use the most appropriate scan basing on my needs... Thanks in advance....
scan for will use indexes and is Rushmore optimisable, scan while is a straightforward iteration while the condition is true.
 
If you need the difference, you'll need it, while works differently than for, as demonstrated, independent from Rushmore optimization usage or not. If you don't realize a difference, the question that raises to me rather is, what conditions you apply to what data. If data is sorted, for example by setting order with an index on a field, and you scan while indexfield=x, then by sorting by that column the behavior becomes the same than for. For is better in that context, but you can't say for always fits your needs and therefore is better. Foir and while have different meanings and you use the one that fits your need.

There's also not a general way to turn a while loop into a for loop or vice versa, as exists with other things. For example you can turn a left join to a right join or vice versa, so none of them is better than the other, but for and while ork differently, as demonstrated, so only use the one you need.

If it never came to your mind that while could end erlier than finding all records, then you already made a mistake of using it, and the condition you need is for, but nobody can tell what you need and forget to get am advice telling that for is better and never use while. As their meaning differs, you have to use what's appropriate.

To use for in situations you'd need while, actually, can be made possible by sorting differently (or at all), but when you want to traverse all records fulfilling a condition while was the wrong kind of cloop to use, in the first place. Because sorting differently can mean you pick other records with while condition. For, on the other side, will always find all records fulfilling a condition, no matter how they are currently sorted.
 
It may also be helpful you revist threads you asked about SCAN previously and see what you forgot about them.
There are other aspects in these threads, some of them totally unrelated, but maybe it helps to put everything into perspective.
 
Last edited:
Hi everyone...i have been using these two... scan for and scan while... and it works perfectly may you help me explain further how these two works so that i could use the most appropriate scan basing on my needs... Thanks in advance....
I was gonna answer but all these other guys kind of beat the answer to death already. :) I absolutely couldn't think of a thing to add!
 
I'm sure there's more to say, if Mandy would tell how she managed to use these two variants interchangably while they are not (no pun intended). But thanks for being a satisfied customer and colleague, Doug.

I mean, we could for example point out there's the concept of iteration by a counter, while and until loops in many programming languages, and these constructs can partly be used interchangably, there's always a way to turn a while loop into an until loop, but depending on the situation or problem one of them is more straight forward to be formulated.

Both while and until loops are also working on the basis of the computer science concept of loop invariants. I'll not go down that rabbit hole, though.

In short the different options of a command or loop constructs exist for the same reason you have different words having similar meanings in natural languages, to enrich the language and enable you to express what you want to achieve with the code one way or the other. The desire to have less options always points out to me you'd like options to be taken away from you. Why? Because it makess things easier to learn or to be more sure you're not using the wrong thing? In the end everything computer is just 0 or 1. But would you like to learn a programming language that only allows you to express your code in 0s and 1s? Then you only have to learn two letters, isn't that easier? Surely not.

It should be clear by now SCAN FOR And SCAN WHILE work differently. Not only by using Rushmore or not. If there would be no difference, there also would only be the one or the other, generally. There are few exceptions in the VFP language where you can forget about something and never use it or only use one of two things. Like SYS(0) and ID() actually being exactly the same function, of which you can always use ID(), not only because it's shorter but at least a bit better telling what it is. But that's rare in the VFP language. If you don't know how something differs that has differences in the fomrulations, the help reference is a good first place to look into.
 
Last edited:
Hi everyone...i have been using these two... scan for and scan while... and it works perfectly may you help me explain further how these two works so that i could use the most appropriate scan basing on my needs... Thanks in advance....
There are many great answers so I hope I don't contradict any but one thing I'd make clear is the FOR and WHILE clauses are not mutually exclusive, I frequently use both together. There are scenarios where using both together can be beneficial. Especially if you want to reduce the amount of indented blocks, perhaps making some code clearer, removing some lines of code because VFP will do other things automatically and SCAN provides some god flexibility.

I'll use quite a specific example. I work in an enormous and very old application and back in the late 1990s, early 2000s, previous coders had a habit of writing code to iterate through rows in a table like the following:

Code:
SELECT bob
SET ORDER TO id
SEEK tnId
IF FOUND()
    DO WHILE id = tnId AND NOT EOF("bob")
        IF {some condition}
            {do some stuff}
        ENDIF
        
        SELECT bob
        SKIP
    ENDDO
ENDIF

...the above code works so it doesn't NEED to be rewritten, but it can be written in a way that doesn't need as many IFs, doesn't need as many SELECT and doesn't need the SKIP. I can only imagine the coders who wrote that either didn't know about SCAN or just didn't like it. It's obviously a preference thing but I don't like seeing that SELECT bob then SKIP bit in the loop, every time I see a DO WHILE ... NOT EOF() I know that I've hit another place where a coder has written a DO WHILE when they probably could have used a SCAN.

Using SCAN and both the FOR and WHILE clauses together the above code can be written something like this...

Code:
SELECT bob
SET ORDER TO id
IF SEEK(tnId)
    SCAN REST ;
            FOR {some condition} ;
            WHILE id = tnId
        
        {do some stuff}
    ENDSCAN
ENDIF

Separate to the SCAN discussion, I've combined the SEEK and IF FOUND() lines, then because SCAN is a great flexible command that is a good alternative to the DO WHILE ... SKIP loop, I've replaced the whole DO WHILE with a SCAN REST ... WHILE. This means straight away I don't have to manually call EOF(), with the added bonus that the SCAN doesn't need to explicitly reselect the alias again, should the {do some stuff} section have anything that selected a different table, the ENDSCAN will return the selection to "bob" automatically. So that means I can drop the SELECT bob, SKIP. Also, the flexibility of SCAN meaning the inner IF {some condition} from the first example can be merged into the SCAN (in this example) because the IF surrounds everything except the SKIP section.

All in all, by using both FOR and WHILE clauses I can write, what I think is, more elegant code. I certainly find that more readable, especially in the scenario where in the first example the {do some stuff} section is quite long, requiring quite a lot of scrolling to see what is inside the IF, whether the IF has an ELSE, whether there is anything crucial outside the IF but inside the DO WHILE. Obviously, if there was an ELSE or crucial code completely outside the IF but inside the loop, I wouldn't be able to simply rewrite as above but most of the time, in my app, it does follow that same pattern from my example, so I could rewrite, if I had the inclination, and that is thanks to the flexibility of SCAN and in particular using the FOR and WHILE clauses together.
 
True, I would add to usage of FOR and WHILE together, the WHILE clause has precedence to end the loop, even when there are further records due to FOR condition. But there are good usages of that, like scanning For unprocessed orderitems only within one specific order, using
Code:
SEEK specificorderid && position on first orderitem of a specific order by the orderid (the data structure of an orderitem needs to have an orderid and unprocessed status besides other fields like product, no of items, etc):
SCAN REST FOR unprocessed WHILE orderid=specificorderid
...
ENDSCAN
What can fail in comparison is
Code:
SEEK specificorderid && position on first orderitem of a specific order by the orderid
SCAN REST WHILE unprocessed
...
ENDSCAN
Because that will only go into all unprocessed items until the first processed item is reached. If, for example, the first orderitem would be proecessed, that would make the scan loop end, even when there are still further unprocessed items after the first.

I would then recommend to do something else, anyway: Combine all of that into a single for condition to loop all unprocessed items of an order, not even seeking for the first item:
Code:
SCAN For orderid=specificorderid and unprocessed
...
ENDSCAN
That only scans records of the specificorderid that are unprocessed=.t.. No need to have a separate FOR or WHILE condition to get there, or even an initial SEEK, the FOR will also find the first record without a seek. Not even talking about the need to first set an order by index to be able to make the SEEK.

All in all that goes back to being able to express the same thing in different ways, as in natural language.
 
Last edited:

Part and Inventory Search

Sponsor

Back
Top