==================================================================== For loops ==================================================================== FriCAS provide the for and in keywords in repeat loops, allowing you to integrate across all elements of a list, or to have a variable take on integral values from a lower bound to an upper bound. We shall refer to these modifying clauses of repeat loops as for clauses. These clauses can be present in addition to while clauses (See )help while). As with all other types of repeat loops, leave (see )help leave) can be used to prematurely terminate evaluation of the loop. The syntax for a simple loop using for is :: for iterator repeat loopbody The iterator has several forms. Each form has an end test which is evaluted before loopbody is evaluated. A for loop terminates immediately when the end test succeeds (evaluates to true) or when a leave or return expression is evaluated in loopbody. The value returned by the loop is the unique value of Void. ------------------------ ``for i in n..m repeat`` ------------------------ If for is followed by a variable name, the in keyword and then an integer segment of the form n..m, the end test for this loop is the predicate i > m. The body of the loop is evaluated m-n+1 times if this number is greater than 0. If this number is less than or equal to 0, the loop body is not evaluated at all. The variable i has the value n, n+1, ..., m for successive iterations of the loop body. The loop variable is a local variable within the loop body. Its value is not available outside the loop body and its value and type within the loop body completely mask any outer definition of a variable with the same name. :: for i in 10..12 repeat output(i**3) 1000 1331 1728 Type: Void The loop prints the values of 10^3, 11^3, and 12^3. :: a := [1,2,3] [1,2,3] Type: List PositiveInteger for i in 1..#a repeat output(a.i) 1 2 3 Type: Void Iterate across this list using "." to access the elements of a list and the # operation to count its elements. This type of iteration is applicable to anything that uses ".". You can also use it with functions that use indices to extract elements. :: m := matrix [[1,2],[4,3],[9,0]] +- -+ | 1 2 | | 4 3 | | 9 0 | +- -+ Type: Matrix Integer Define m to be a matrix. :: for i in 1..nrows(m) repeat output row(m.i) [1,2] [4,3] [9,0] Type: Void Display the rows of m. You can iterate with for-loops. :: for i in 1..5 repeat if odd?(i) then iterate output(i) 2 4 Type: Void Display the even integers in a segment. ----------------------------- ``for i in n..m by s repeat`` ----------------------------- By default, the difference between values taken on by a variable in loops such as :: for i in n..m repeat ... is 1. It is possible to supply another, possibly negative, step value by using the by keyword along with for and in. Like the upper and lower bounds, the step value following the by keyword must be an integer. Note that the loop :: for i in 1..2 by 0 repeat output(i) will not terminate by itself, as the step value does not change the index from its initial value of 1. :: for i in 1..5 by 2 repeat output(i) 1 3 5 Type: Void This expression displays the odd integers between two bounds. :: for i in 5..1 by -2 repeat output(i) 5 3 1 Type: Void Use this to display the numbers in reverse order. ----------------------- ``for i in n.. repeat`` ----------------------- If the value after the ".." is omitted, the loop has no end test. A potentially infinite loop is thus created. The variable is given the successive values n, n+1, n+2, ... and the loop is terminated only if a leave or return expression is evaluated in the loop body. However, you may also add some other modifying clause on the repeat, for example, a while clause, to stop the loop. :: for i in 15.. while not prime?(i) repeat output(i) 15 16 Type: Void This loop displays the integers greater than or equal to 15 and less than the first prime number greater than 15. --------------------- ``for x in l repeat`` --------------------- Another variant of the for loop has the form: :: for x in list repeat loopbody This form is used when you want to iterate directly over the elements of a list. In this form of the for loop, the variable x takes on the value of each successive element in l. The end test is most simply stated in English: "are there no more x in l?" :: l := [0, -5, 3] [0, -5, 3] Type: List Integer for x in l repeat output(x) 0 -5 3 Type: Void This displays all of the elements of the list l, one per line. Since the list constructing expression :: expand [n..m] creates the list :: [n, n+1, ..., m] you might be tempted to think that the loops :: for i in n..m repeat output(i) and :: for x in expand [n..m] repeat output(x) are equivalent. The second form first creates the expanded list (no matter how large it might be) and then does the iteration. The first form potentially runs in much less space, as the index variable i is simply incremented once per loop and the list is not actually created. Using the first form is much more efficient. Of course, sometimes you really want to iterate across a specific list. This displays each of the factors of 2400000: :: for f in factors(factor(2400000)) repeat output(f) [factor= 2, exponent= 8] [factor= 3, exponent= 1] [factor= 5, exponent= 5] Type: Void