HOME | 10. Immutable classes | Try Sather | 12. Exception | download | Post Messages |
function classeshere. A function class can be a value of the MAP type.
Two types of function classes are available: one is ROUT class which is a typical procedure and the other is ITER, a iterator.
01: -- rout.sa 02: -- simple examples for ROUT and ITER 03: 04: class MAIN is 05: 06: -- helper function to treat TUP{INT,INT} 07: aux(tu:TUP{INT, INT}):INT is 08: return tu.t1 + tu.t2; 09: end; 10: 11: -- print function 12: print(obj:$STR, sep:STR) is 13: #OUT + obj + sep; 14: end; 15: 16: 17: main is 18: -- declaring instances of function classes 19: csqrt:ROUT{FLT}:FLT; 20: cpow:ROUT{FLT,FLT}:FLT; 21: ccomp:ROUT{TUP{INT,INT}}:INT; 22: istep:ITER{once INT,once INT,once INT}:INT; 23: 24: -- assigning the function class instances 25: csqrt:=bind(_.sqrt); 26: cpow:=bind(_.pow(_)); 27: ccomp:=bind(aux(_)); 28: istep:=bind(_.step!(_,_)); 29: 30: -- calling the function class instances 31: print(csqrt.call(2.0), "\n"); -- 1.414.... 32: print(cpow.call(0.99999, 300.0), "\n"); -- 0.997 33: print(ccomp.call(#TUP{INT,INT}(1,2)), "\n"); -- 3 34: loop 35: print(istep.call!(1,5,3), " "); -- 1 4 7 10 13 36: end; 37: #OUT + "\n"; 38: end; 39: end;
Line | Explanation |
---|---|
19 — 22 | declaring to use function classes with arguments and type of the return value. |
25 — 28 | Method bind is to assign a procedure. '_' represents an argument. As a complicate procedures cannot be the argument of the bind, you should define the procedure as a single method and give it to the bind. |
31 — 37 | Use call and call! methods to call ROUT and ITER type function classes, respectively. |
In the above code, I declared the instances of function classes and then assigned them separetely just for explanation. You can do them simultaneously, however, like:
cpow:ROUT{FLT,FLT}:FLT:=bind(_.pow(_));
$ sacomp rout.sa -o rout $ ./rout 1.41421 0.997 3 1 4 7 10 13
01: -- horder.sa 02: -- examples for higher order functions for ARRAY{INT} 03: 04: class MAIN is 05: const iarr:ARRAY{INT}:=|0,9,2,7,3,4,1,5,8,6|; 06: 07: 08: -- print function 09: print(obj:$STR, sep:STR) is 10: #OUT + obj + sep; 11: end; 12: 13: 14: -- filtering 15: select_even:ARRAY{INT} is 16: return iarr.remove_if(bind(_.is_odd)); 17: end; 18: 19: -- mapping 20: sq:ARRAY{INT} is 21: a:ARRAY{INT}; 22: a:=iarr.copy; 23: a.map(bind(_.pow(2))); 24: return a; 25: end; 26: 27: -- folding 28: sum:INT is 29: return iarr.reduce(bind(_.plus(_))); 30: end; 31: 32: -- a helper function for order_by_desc 33: gt(i,j:INT):BOOL is 34: return i > j; 35: end; 36: 37: -- sorting 38: order_by_desc:ARRAY{INT} is 39: a:ARRAY{INT}; 40: a:=iarr.copy; 41: a.insertion_sort_by(bind(gt(_,_))); 42: return a; 43: end; 44: 45: 46: main(av: ARRAY{STR}) is 47: print(select_even, "\n"); 48: print(sq, "\n"); 49: print(sum, "\n"); 50: print(order_by_desc, "\n"); 51: end; 52: end;
$ sacomp horder.sa -o horder $ ./horder {0,2,4,8,6} {0,81,4,49,9,16,1,25,64,36} 45 {9,8,7,6,5,4,3,2,1,0}
01: -- rpcalc.sa: a simple reverse polish calculator, second version 02: 03: class OPERATORS is 04: 05: attr biop:MAP{STR,ROUT{FLTD,FLTD}:FLTD}; -- MAP of binary operators 06: attr unop:MAP{STR,ROUT{FLTD}:FLTD}; -- unary operators 07: 08: create:SAME is 09: return new.init; 10: end; 11: 12: init:SAME is 13: init_biop; 14: init_unop; 15: return self; 16: end; 17: 18: init_biop is -- adding binary operators to the hash table 19: biop:=#; 20: biop["+"]:=bind(_.plus(_)); 21: biop["-"]:=bind(_.minus(_)); 22: biop["*"]:=bind(_.times(_)); 23: biop["/"]:=bind(_.div(_)); 24: biop["^"]:=bind(_.pow(_)); 25: end; 26: 27: init_unop is -- adding unary operators to the hash table 28: unop:=#; 29: unop["exp"] := bind(_.exp); 30: unop["log"] := bind(_.log); 31: unop["sin"] := bind(_.sin); 32: unop["cos"] := bind(_.cos); 33: unop["tan"] := bind(_.tan); 34: unop["asin"]:= bind(_.asin); 35: unop["acos"]:= bind(_.acos); 36: unop["atan"]:= bind(_.atan); 37: end; 38: 39: is_operator(s:STR):BOOL is -- is it an operatorˇ© 40: return is_biop(s) or is_unop(s); 41: end; 42: 43: is_biop(s:STR):BOOL is -- is it binaryˇ© 44: return biop.has_ind(s); 45: end; 46: 47: is_unop(s:STR):BOOL is -- unaryˇ© 48: return unop.has_ind(s); 49: end; 50: 51: apply(s:STR, a:FLTD):FLTD is -- calculating with a unary operator 52: return unop[s].call(a); -- use it like apply("log", 3.3) 53: end; 54: 55: apply(s:STR, a,b:FLTD):FLTD is -- calculating with a binary operator 56: return biop[s].call(a,b); -- use it like apply("+", 1.1, 2.3) 57: end; -- you can override methods if they have different arguments. 58: 59: end; --OPERATORS 60: 61: 62: 63: class MAIN is 64: 65: const re:REGEXP:=REGEXP::regexp("^[+\\-]?[0-9]+\\.?[0-9]*$", false); -- a regular expression to see if the string represents a real number. 66: attr stack:STACK{FLTD}; 67: attr op:OPERATORS; 68: 69: is_number(word:STR):BOOL is -- is it a real numberˇ© 70: return re.match(word); 71: end; 72: 73: bicalc(word:STR) is -- using a binary operator 74: f1,f2 :FLTD; -- pop twice, calculate, then push the result 75: f2:=stack.pop; 76: f1:=stack.pop; 77: stack.push(op.apply(word,f1,f2)); 78: end; 79: 80: push_to_stack(word:STR) is -- pushing a real number on to the stack 81: stack.push(word.cursor.get_fltd); 82: end; 83: 84: clear_stack is -- clearing the stack 85: a:FLTD; 86: loop 87: while!(~stack.is_empty); 88: a:=stack.pop; 89: end; 90: end; 91: 92: show_stack:STR is -- converting the stack to a string 93: s:STR:="> "; 94: loop 95: s:= s + stack.reverse_elt!.str + " "; 96: end; 97: return s; 98: end; 99: 100: main(av: ARRAY{STR}) is 101: line, word:STR; 102: stack:=#; 103: op:=#; -- making an instance of the OPERATORS class 104: loop 105: #OUT + show_stack; 106: line:=#IN.get_str + " "; 107: loop 108: word := line.split!(' '); 109: word := word.head(word.size-1); 110: if op.is_unop(word) then stack.push(op.apply(word, stack.pop)); -- if unary, pop once, calculate, then push 111: elsif op.is_biop(word) then bicalc(word); -- if binary, call bicalc 112: elsif is_number(word) then push_to_stack(word); -- push if number 113: elsif word="clear" then clear_stack; -- clear the stack if "clear" 114: elsif word="end" then UNIX::exit(0); -- terminate if "end" 115: end; 116: end; 117: end; 118: end; 119: end;
$ sacomp rpcalc.sa -o rpcalc $ ./rpcalc -- bold strings represent user input > 2.2 0.8 + 4.7 1.7 - * -- (2.2 + 0.8) * (4.7 - 1.7) > 9 0.5 ^ -- 9 ^ 0.5 > 3 sin -- sin(3) > 0.14112 asin -- asin(0.14112) > 0.141593 10 2 ^ -- 0.141593 (10 ^ 2) > 0.141593 100 * -- 0.141593 * 100 > 14.1593 end $
Download and play with the code presented in this chapter.
HOME | 10. Immutable classes | Try Sather | 12. Exception | download | Post Messages |