HOME | 3. Playing with Sather | Try Sather | 5. Classes | Post Messages |
The loop terminates when a iterator indicate the break.
loop (something) iterator (something) end;You can put iterators anyplace in the loop.
01: -- primitive counting prime numbers program 02: 03: class MAIN is 04: 05: top_while(n:INT) is 06: i:INT := 0; 07: #OUT + "Top while test:\n"; 08: loop 09: while!(i < n); 10: #OUT + "repeat: " + i + "\n"; 11: i := i+1; 12: end; 13: #OUT + "\n"; 14: end; 15: 16: bottom_while(n:INT) is 17: i:INT := 0; 18: #OUT + "Bottom while test:\n"; 19: loop 20: #OUT + "repeat: " + i + "\n"; 21: i := i+1; 22: while!(i < n); 23: end; 24: #OUT + "\n"; 25: end; 26: 27: middle_while(n:INT) is 28: i:INT := 0; 29: #OUT + "Middle while test:\n"; 30: loop 31: #OUT + "before while: " + i + "\n"; 32: while!(i < n); 33: #OUT + "after while: " + i + "\n"; 34: i := i+1; 35: end; 36: #OUT + "\n"; 37: end; 38: 39: 40: 41: 42: main(av:ARRAY{STR}) is 43: if av.size = 2 then 44: n:INT := av[1].cursor.get_int; 45: top_while(n); 46: bottom_while(n); 47: middle_while(n); 48: else 49: #ERR + "Usage: while N\n" 50: end; 51: end; 52: end;
$ ./while 5 Top while test: repeat: 0 repeat: 1 repeat: 2 repeat: 3 repeat: 4 Bottom while test: repeat: 0 repeat: 1 repeat: 2 repeat: 3 repeat: 4 Middle while test: before while: 0 after while: 0 before while: 1 after while: 1 before while: 2 after while: 2 before while: 3 after while: 3 before while: 4 after while: 4 before while: 5Iterator while! repeats the loop while the argument is true, which is similar to other languages. On the other hand, until! exit from the loop when the argument is true. Iterator bleak! is to exit from the loop unconditionally.
01: -- primitive counting prime numbers program 02: 03: class MAIN is 04: 05: until_test(n:INT) is 06: i:INT:=0; 07: loop 08: #OUT + i + "\n"; 09: if i= n then break!; end; 10: until!(i = 1000); 11: i := i+1; 12: end; 13: end; 14: 15: main(av:ARRAY{STR}) is 16: if av.size = 2 then 17: n:INT := av[1].cursor.get_int; 18: until_test(n); 19: else 20: #ERR + "Usage: until_break N\n" 21: end; 22: end; 23: end;
int_iter.sa
01: -- iterators of INT class 02: -- 03: -- downto!(once i:SAME):SAME 04: -- **** Yield successive integers from self down to `i' inclusive. 05: -- for!(once i:SAME):SAME 06: -- **** Yields `i' successive integers starting with self. 07: -- product!(i:SAME):SAME 08: -- **** Yields the product of all previous values of `i'. 09: -- step!(once num,once step:SAME):SAME 10: -- **** Yield `num' integers starting with self and stepping by `step'. 11: -- stepto!(once to,once by:SAME): SAME 12: -- **** Yield succeeding integers from self to `to' by step `by'. Might quit immediately if self is already `beyond'. 13: -- sum!(i:SAME):SAME 14: -- **** Yields the sum of all previous values of `i'. 15: -- times! 16: -- **** Yields self times without returning anything. 17: -- times!:SAME 18: -- **** Yield successive integers from 0 up to self-1. 19: -- up!:SAME 20: -- **** Yield successive integers from self up. 21: -- upto!(once i:SAME):SAME 22: ---------------- 23: 24: class MAIN is 25: 26: test_downto(start, last:INT) 27: pre start >= last 28: is 29: #OUT + "Test for " + start + ".downto!(" + last + "): "; 30: loop 31: #OUT + start.downto!(last) + " "; 32: end; 33: #OUT + "\n"; 34: end; 35: 36: test_for(start, last :INT) 37: pre start <= last 38: is 39: #OUT + "Test for " + start + ".for!(" + last + "): "; 40: loop 41: #OUT + start.for!(last) + " "; 42: end; 43: #OUT + "\n"; 44: end; 45: 46: test_step(start, last, step :INT) is 47: #OUT + "Test for " + start + ".step!(" + last + ", " + step + "): "; 48: loop 49: #OUT + start.step!(last, step) + " "; 50: end; 51: #OUT + "\n"; 52: end; 53: 54: test_stepto(start, last, step :INT) is 55: #OUT + "Test for " + start + ".stepto!(" + last + ", " + step + "): "; 56: loop 57: #OUT + start.stepto!(last, step) + " "; 58: end; 59: #OUT + "\n"; 60: end; 61: 62: test_times0(n:INT) 63: pre n>=0 64: is 65: #OUT + "Test for " + n + ".times!: "; 66: loop 67: n.times!; 68: #OUT + "Hey! "; 69: end; 70: #OUT + "\n"; 71: end; 72: 73: test_times1(n:INT) 74: pre n>=0 75: is 76: i:INT; 77: #OUT + "Test for " + n + ".times! returning INT: "; 78: loop 79: i := n.times!; 80: #OUT + "Hey!(" + i + ") "; 81: end; 82: #OUT + "\n"; 83: end; 84: 85: test_up(n:INT) 86: pre n >= 0 87: is 88: i:INT; 89: #OUT + "Test for " + n + ".up!: "; 90: loop 91: i := n.up!; 92: #OUT + i + " "; 93: if i = n+ 9 then #OUT + "break\n"; break!; end; 94: end; 95: end; 96: 97: test_upto(start, last :INT) is 98: #OUT + "Test for " + start + ".upto!(" + last + "): "; 99: loop 100: #OUT + start.upto!(last) + " "; 101: end; 102: #OUT + "\n"; 103: end; 104: 105: test_product(m,n:INT) 106: pre n >= m 107: is 108: p:INT; 109: #OUT + "Test for product!: " + m + " * ... * " + n + " = "; 110: loop 111: p := INT::product!(m.upto!(n)); 112: end; 113: #OUT + p + "\n"; 114: end; 115: 116: test_sum(m,n:INT) 117: pre n >= m 118: is 119: p:INT; 120: #OUT + "Test for sum!: " + m + " + ... + " + n + " = "; 121: loop 122: p := INT::sum!(m.upto!(n)); 123: end; 124: #OUT + p + "\n"; 125: end; 126: 127: main(av:ARRAY{STR}) is 128: if av.size = 4 then 129: a:ARRAY{INT} :=#(3); 130: i:INT; 131: loop 132: i:= 3.times!; 133: a[i]:= av[i+1].cursor.get_int; 134: end; 135: test_times0(a[1]); 136: test_times1(a[1]); 137: test_up(a[0]); 138: test_upto(a[0],a[1]); 139: test_downto(a[1], a[0]); 140: test_for(a[0], a[1]); 141: test_step(a[0], a[1], a[2]); 142: test_stepto(a[0], a[1], a[2]); 143: test_sum(a[0], a[1]); 144: test_product(a[0], a[1]); 145: 146: else 147: #ERR + "Usage: int_iter MIN MAX STEP\n" 148: end; 149: end; 150: end;
$ sacomp -chk int_iter.sa -o int_iter $ ./int_iter 1 6 2 Test for 6.times!: Hey! Hey! Hey! Hey! Hey! Hey! Test for 6.times! returning INT: Hey!(0) Hey!(1) Hey!(2) Hey!(3) Hey!(4) Hey!(5) Test for 1.up!: 1 2 3 4 5 6 7 8 9 10 break Test for 1.upto!(6): 1 2 3 4 5 6 Test for 6.downto!(1): 6 5 4 3 2 1 Test for 1.for!(6): 1 2 3 4 5 6 Test for 1.step!(6, 2): 1 3 5 7 9 11 Test for 1.stepto!(6, 2): 1 3 5 Test for sum!: 1 + ... + 6 = 21 Test for product!: 1 * ... * 6 = 720
See http://www.icsi.berkeley.edu/~sather/Documentation/Library/LibraryBrowser/short-ARRAY%7B_%7D.html for detailed information.
array_iter.sa
01: -- example of iterators in the ARRAY class 02: 03: class MAIN is 04: 05: const a1:ARRAY{INT}:=|1,2,3,4,5|; 06: const a2:ARRAY{INT}:=|7,11,13,17,19|; 07: 08: show_array(a:ARRAY{INT}, name:STR) is 09: i,j:INT; 10: loop 11: i:=a.ind!; 12: j:=a.elt!; 13: #OUT + name + "[" + i + "] = " + j + ", "; 14: end; 15: #OUT + "\n"; 16: end; 17: 18: ipro(a1,a2:ARRAY{INT}):INT 19: pre a1.size = a2.size 20: is 21: p:INT; 22: loop 23: p := INT::sum!(a1.elt! * a2.elt!); 24: end; 25: return p; 26: end; 27: 28: add_arr(a1, a2:ARRAY{INT}):ARRAY{INT} 29: pre a1.size = a2.size 30: is 31: ar :ARRAY{INT} := #(a1.size); 32: loop 33: ar.set!(a1.elt! + a2.elt!); 34: end; 35: return ar; 36: end; 37: 38: main is 39: #OUT + "a1 = " + a1 + "\n" + "a2 = " + a2 + "\n\n"; 40: show_array(a1, "a1"); 41: show_array(a2, "a2"); 42: #OUT + "a1 + a2 = " + add_arr(a1, a2) + "\n"; 43: #OUT + "inner product of a1 and a2 = " + ipro(a1, a2) + "\n"; 44: end; 45: end;
takafumi@suse:~/doc/monthly/06-05/sather> sacomp -chk array_iter.sa -o array_iter takafumi@suse:~/doc/monthly/06-05/sather> ./array_iter a1 = {1,2,3,4,5} a2 = {7,11,13,17,19} a1[0] = 1, a1[1] = 2, a1[2] = 3, a1[3] = 4, a1[4] = 5, a2[0] = 7, a2[1] = 11, a2[2] = 13, a2[3] = 17, a2[4] = 19, a1 + a2 = {8,13,16,21,24} inner product of a1 and a2 = 231
str_iter.sa
01: -- iterators of STR class 02: -- 03: -- chunk!(chunk_size: INT): STR 04: -- **** Yield successive chunks of self, defined by the chunk size "size" 05: -- elt!(once beg:INT):CHAR 06: -- **** Yield the characters of self in order starting at `beg'. Self may be void. Modified (ben) 07: -- elt!(once beg,once num:INT):CHAR 08: -- **** Yield 'num' characters of self in order starting at `beg'. Self may be void. Modified (ben) 09: -- elt!:CHAR 10: -- **** Yield the characters of self in order. Self may be void. Modified (ben) 11: -- ind!:INT 12: -- **** Yield the induces of the characters of self in order. Self may be void. Modified (ben) 13: -- separate!(s:$STR):STR 14: -- **** On the first iteration just outputs `s', on successive iterations it outputs self followed by `s'. Useful for forming lists, 15: -- ____loop_#OUT_+_",_".separate!(a.elt!)_end; 16: -- split!(once c: CHAR): STR 17: -- **** Yield successive substrings that are separated by the character "c" 18: ---------------------------------------------------------------------------------------- 19: 20: 21: class MAIN is 22: 23: test_chunk is 24: s:STR := "abcdefghijklmnopqrstuvwxyz@"; 25: s1:STR; 26: loop 27: s1 := s1 + s.chunk!(3) + " "; 28: end; 29: #OUT + "Test of (" + s + ").chunk!(3): " + s1 + "\n"; 30: end; 31: 32: test_split is 33: s:STR:= "192.168.1.1"; 34: #OUT + "Test of (" + s + ").split('.'): "; 35: loop 36: #OUT + (s+".").split!('.') + " "; -- add "." at the end 37: end; 38: #OUT + "\n"; 39: 40: end; 41: 42: test_separate is 43: a:ARRAY{INT}:=|1,2,3,4,5,6,7|; 44: #OUT + "Test of \" \".separate(" + a + ".elt!): "; 45: loop 46: #OUT + " ".separate!(a.elt!); 47: end; 48: #OUT + "\n"; 49: end; 50: 51: main is 52: test_chunk; 53: test_split; 54: test_separate; 55: end; 56: end;
takafumi@suse:~/doc/monthly/06-05/sather> sacomp str_iter.sa -o str_iter takafumi@suse:~/doc/monthly/06-05/sather> ./str_iter Test of (abcdefghijklmnopqrstuvwxyz@).chunk!(3): abc def ghi jkl mno pqr stu vwx yz@ Test of (192.168.1.1).split('.'): 192. 168. 1. 1. Test of " ".separate({1,2,3,4,5,6,7}.elt!): 1 2 3 4 5 6 7
It is completely the same as typical function definition except the iterator name ends with '!'. The arguments qualified by once are evaluated once when the iterator is called first. The iterator returns a value when it meets yield with stopping the operation. The operation starts again when the iterator is called next time.
Following code defines a iterator that produces geometric sequences (geo!(once a0, once r:FLTD):FLTD).
01: -- iterator for geometrical progressions 02: 03: class MAIN is 04: 05: geo!(once a0, once r:FLTD):FLTD is 06: a:FLTD:=a0; 07: loop 08: yield a; 09: a := a * r; 10: end; 11: end; 12: 13: main is 14: g1, g2 : FLTD; 15: #OUT + "User defined iterator: geo!(a0, r, FLTD)\n"; 16: loop 17: 10.times!; 18: g1 := geo!(1.0d, 2.0d); 19: g2 := geo!(1.0d, 0.5d); 20: #OUT + g1 + " * " + g2 + " = " + (g1*g2) + "\n"; 21: end; 22: end; 23: end;
takafumi@suse:~/doc/monthly/06-05/sather> sacomp geo.sa -o geo takafumi@suse:~/doc/monthly/06-05/sather> ./geo User defined iterator: geo!(a0, r, FLTD) 1 * 1 = 1 2 * 0.5 = 1 4 * 0.25 = 1 8 * 0.125 = 1 16 * 0.0625 = 1 32 * 0.03125 = 1 64 * 0.015625 = 1 128 * 0.0078125 = 1 256 * 0.00390625 = 1 512 * 0.00195312 = 1You can exit from the loop explicitly using quit. The quit is effective only in the loop. The while!, for instance, can be defined like as follows.
my_while!(predicate :BOOL) is loop if predicate then yield; else quit; end; end; end;
HOME | 3. Playing with Sather | Try Sather | 5. Classes | Post Messages |