Felix supports a radical new programming paradigm -- programming with circuits. In this game, the players are wires and chips: we have a powerful concept of modularity and components.
Below is a 'realistic' example. Two things need to be noted. The first is that the technique can be difficult to use. I got it wrong first time.. but no error, the circuit just didn't do anything. This is what you expect when you connect the wrong pins of some chips together of course. The second thing to note is that we need more sugar! But we need examples to see what to provide. The chip based example is slighly more abstract and modular than the traditional code, however this is just an accident: standard functional techniques like currying could have provided more abstraction. The key difference is in the control protocol. The functional code 'just works' but it is impossible to control invert. The fibrated code (chips and wires model) is already control neutral. The components *cooperate*: none is a 'subroutine' called by another 'master'. This control neutrality is a *mandatory* property of a component, and this discredits subroutines, and in particular it destroys any notion that basic functional programming is any good. It explains why functional code rapidly turns into switch spaghetti. Advanced techniques like continuation passing don't have this problem .. but then that is just what Felix is doing! I'll make more comments in subsequent emails in this thread. The code here provides a procedure for integrating an arbitrary function based on Newton's method. This works by viewing the graph of the function as a bar graph, and adding up the area of the bars. We then try to guess how many bars we need to get an accurate integral by increasing the number until the difference between two successive approximation is small enough. This procedure does not work, as you will see by examining the output, but that is beside the point :) //////////////////////////////////////////////////////////// #import <flx.flxh> comment """ integrate f from a to b by drawing a bar chart with n bars and adding the areas of the bars up: Newton method """; fun newton ( f: double -> double, a:double, b: double, n:int when a <= b and n>0 ): double = { width := b - a; barwidth := width / double n; var sum = 0.0; var i:int; forall i in 0 upto n-1 do x := a + width * (double i + 0.5)/double n; height := f x; sum += barwidth * height; done; return sum; } proc test1 { comment """ Since integral (sin x) = -cos x, integral (sin x) from 0 to x is -cos x - -cos 0 = -cos x - -1 = 1 - cos x """; print "Newton integral, n=200\n"; var x = 0.0; val pi = 3.141; while {x < pi} { y := newton (sin of (double), 0.0, x, 200); r := 1.0 - cos x; // the right answer e := y - r; // error print$ f"x=%f, sin x = %f, 1-cos x = %f, integ (sin x)= %f, error = %f\n" (x, sin x, r, y, e) ; x += 0.1; }; } test1; comment """ Now, we use a Cauchy condition to evaluate a definite integral. We start with n = 4, and calculate y' = integral (f,a,b,n) Then increase n and calculate y = integral (f,a,b,n) and delta = abs(y-y') is difference between the two terms. We continue until the difference is less than some given epsilon """; fun cauchy( f:double -> double, a: double, b: double, epsilon: double when a <= b and epsilon > 1.0e-14 ): double = { var n = 4; var y0 = newton (f, a, b, n); retry:> n = n * 7/4; var y1 = newton (f, a, b, n); if abs (y1 - y0) <= epsilon do return y1; else goto retry; done; } proc test2 { print "Newton integral with feedback and Cauchy termination\n"; var x = 0.0; val pi = 3.141; while {x < pi} { y := cauchy (sin of (double), 0.0, x, 1.0e-12); r := 1.0 - cos x; // the right answer e := y - r; // error print$ f"x=%f, sin x = %f, 1-cos x = %f, integ (sin x)= %f, error = %f\n" (x, sin x, r, y, e) ; x += 0.1; }; }; test2; comment """ remodel the whole thing using chips """; typedef idouble = ischannel[double]; typedef odouble = oschannel[double]; typedef iint = ischannel[int]; typedef oint = oschannel[int]; proc Sin(i:idouble, o:odouble) { again:> var &x : double <- read i; y := sin x; write (o,y); goto again; } proc Newton( fout:odouble,fin:idouble, a:double, bin:idouble, nin:iint, res:odouble ) { again:> var &b : double <- read bin; width := b - a; var &n : int <- read nin; barwidth := width / double n; var sum = 0.0; var i:int; forall i in 0 upto n-1 do x := a + width * (double i + 0.5)/double n; write (fout, x); var &height : double <- read fin; sum += barwidth * height; done; write (res,sum); goto again; } proc Cauchy( bin:idouble, bout:odouble, nout:oint, yin:idouble, epsilon:double, y2out:odouble when epsilon > 1.0e-14 ) { again:> var n = 4; var &b:double <- read bin; retry:> write (bout, b); write (nout, n); var &y0 : double <- read yin; write (bout, b); n = n * 7/4; write (nout, 4); var &y1 : double <- read yin; if abs (y1 - y0) <= epsilon do write (y2out,y1); goto again; else goto retry; done; } proc make_circuit (input: &odouble, output: &idouble) { // xin--> [sin] --> yout // // b2in, nin, yin -> [Newton] -> xout, y2out // // bin, y2in -> [Cauchy] -> b2out, nout, rout // // // define the wires var xin, xout = mk_ioschannel_pair[double](); var yin, yout = mk_ioschannel_pair[double](); var y2in, y2out = mk_ioschannel_pair[double](); var bin, bout = mk_ioschannel_pair[double](); var b2in, b2out = mk_ioschannel_pair[double](); var nin, nout = mk_ioschannel_pair[int](); var rin, rout = mk_ioschannel_pair[double](); // define the chips spawn_fthread { Sin (xin, yout); }; spawn_fthread { Newton (xout, yin, 0.0, b2in, nin, y2out); }; spawn_fthread { Cauchy (bin, b2out, nout, y2in, 1.0e-12, rout); }; *input = bout; *output = rin; } proc test3() { print "FIBRATED Newton integral" " with feedback and Cauchy termination\n" ; var bout: odouble; var rin: idouble; make_circuit(&bout, &rin); var x = 0.0; val pi = 3.141; while {x < pi} { write (bout, x); var &y : double <- read rin; r := 1.0 - cos x; // the right answer e := y - r; // error print$ f"x=%f, sin x = %f, 1-cos x = %f, integ (sin x)= %f, error = %f\n" (x, sin x, r, y, e) ; x += 0.1; }; }; test3; -- John Skaller <skaller at users dot sf dot net> Felix, successor to C++: http://felix.sf.net ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/ _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language