Author:halw

Date:2010-02-05T22:58:35.000000Z


git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@439 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
halw
2010-02-06 18:23:09 +00:00
parent 6f73db5fec
commit 6cf8623ff5

View File

@@ -64,7 +64,7 @@ Now for the two loop examples:
my_list.forth
end
</code>
Loop example 1.
''Loop example 1.''
and:
@@ -72,16 +72,105 @@ and:
<code>
across my_list as ic loop print (ic.item) end
</code>
Loop example 2.
''Loop example 2.''
At first observation, it may not appear that both of these examples are using the same language construct. But, indeed, they are simply two different forms of a single language construct, as you will see.
In fact, these two examples illustrate the two basic usage forms of the loop construct in Eiffel. The two basic forms of the Eiffel loop construct can be differentiated by the parts of the construct with which they begin.
Of course, there is no requirement that ''Loop example 1'' occupy multiple lines, and ''Loop example 2'' occupy only one line. ''Loop example 1'' could have been written like this:
<code>
from my_list.start until my_list.off loop print (my_list.item) my_list.forth end
</code>
just as ''Loop example 2'' could have been written to take multiple lines. It comes down to a matter of what can be read easily as a single line.
The form shown in Loop example 1 begins with an ''Initialization'' part ( <code>from my_list.start</code> ), which starts with the keyword <code>from</code>. Let's call this form the '''traditional''' form. So, the type of loop you see in Loop example 1 has been the traditional mechanism for traversing data structures. However, extensions to Eiffel's loop construct have provided a more concise way of expressing the same traversal.
In fact, these two examples illustrate the two basic usage forms of the loop construct in Eiffel. The two basic forms can be differentiated by the parts of the construct with which they begin.
This is the form shown in Loop example 2. It begins with an ''Iteration'' part ( <code>across my_list as c</code> ), which starts with the keyword <code>across</code>. We'll call this form the '''iteration''' form.
The form shown in ''Loop example 1'' begins with an ''Initialization'' part ( <code>from my_list.start</code> ), which starts with the keyword <code>from</code>. Let's call this form the '''traditional''' form. So, the type of loop you see in ''Loop example 1'' has been the traditional mechanism for accomplishing iterative computation, including iterating across data structures. However, extensions to Eiffel's loop construct have provided a more concise way of expressing traversing "iterable" structures.
This is the form shown in ''Loop example 2''. It begins with an ''Iteration'' part ( <code>across my_list as c</code> ), which starts with the keyword <code>across</code>. We'll call this form the '''iteration''' form.
====A closer look at the ''traditional'' form====
What is happening in ''Loop example 1''? Let's dissect it and see.
First there is the ''initialization'' part:
<code>
from
my_list.start
</code>
''Initialization part.''
The first thing to occur in the execution of the traditional loop is the execution of any instructions in the initialization part (it is permissible for the initialization part to be empty of instructions, but the keyword <code>from</code> must be present to distinguish the traditional loop form). In our example, the feature <code>start</code> is applied to <code>my_list</code> which will attempt to set the list cursor to the first element in <code>my_list</code>.
The ''Exit condition'' part:
<code>
until
my_list.off
</code>
''Exit condition part.''
The exit condition part of the loop construct defines the conditions under which the loop body (explained below) should no longer be executed. In our example, the loop will no long execute if the cursor is "off", that is, there is no current item. So, if the list is empty, the loop body will not execute at all.
The ''<code>loop</code> body'' part:
<code>
loop
print (my_list.item)
my_list.forth
</code>
''<code>loop</code> body part.''
The loop body part contains the sequence of instructions to be executed during each iteration. In the example, that includes printing the current list item and then advancing the cursor. At some point, the cursor will pass the last item in the list, causing the exit condition to become true and stop the loop's execution. So, at the risk of stating the obvious, the key to loops that always complete is to ensure that there is something in the loop body that is guaranteed always to cause the exit condition eventually to become true. Loop correctness will discussed in more detail later.
And finally, there's the ''End'' part:
<code>
end
</code>
''End part.''
====A closer look at the ''iteration'' form====
Now let's examine the iteration form used in ''Loop example 2.''
The example begins with an iteration part:
<code>
across my_list as ic
</code>
''Iteration part.''
The iteration form is special in the sense that it is designed to work with objects which are ''iterable'', usually data structures. The iteration form always targets a particular object (usually a data structure) based on a class that inherits, either directly or indirectly from the library class <code>ITERABLE</code>. The iteration part specifies such a target for the iteration, in the case of our example, the target is <code>my_list</code>.
The "<code>as ic</code>" indicates that a local iteration cursor object referenced by the name <code>ic</code>, and available only for the scope of the iteration, will be created to effect the iteration. The element of <code>my_list</code> which is currently referenced by the cursor <code>ic</code> is accessed through <code>ic.item</code> as you see in the loop body:
<code>
loop print (ic.item)
</code>
''<code>loop</code> body part''.
And lastly, of course, the iteration form includes an end part ... at the end.
Notice that the loop body does not contain the call to the structure's <code>forth</code> feature, as our example in traditional form did. Neither do you see the call to <code>start</code> nor the check of <code>off</code> in the exit condition. The iteration form abstracts these for you, relieving you of their burden ... while eliminating some opportunities for error.
Notice also that the call "<code>print (ic.item)"</code>" accesses the current item as "<code>ic.item"</code>" versus "<code>my_list.item"</code>" in the traditional form. This is because in the iteration form, access to the current item is through the cursor variable, "<code>ic</code>" in the case of ''Loop example 2''.
Concerning cursors, both ways of using the loop construct to traverse a structure employ a cursor. In the traditional usage, the cursor is internal to the structure object. In the case of the example, that would be the instance of <code>LINKED_LIST [STRING]</code> called <code>my_list</code>. Applying the feature <code>item</code> to <code>my_list</code> retrieves the list element currently referenced by the cursor. In the iteration version of traversal, the variable <code>ic</code> holds the iteration cursor, external to the list object. So, you apply <code>ic.item</code> to get the current list element. The advantage to the external cursor is that multiple traversals of the structure can occur simultaneously without interfering with one another. This is possible in the traditional usage, but only by saving and restoring the structure's cursor.
====The ''iteration'' form as a boolean expression====
In ''Loop example 2'', the loop behaves as an instruction. But it is possible to have the iteration loop form behave as a boolean expression. This is helpful in cases in which you might want to ask a question that can only be answered by traversing all or part of a structure.
To get this effect, you use the iteration form with one of two alternative body notations, the ''<code>all</code> body'' or the ''<code>some</code> body'' in place of the ''<code>loop</code> body''.
===Debug===