There was some discussion in the ChuckMoore page that Forth is no more difficult to read than C. Here's some sample Forth code, and some C code that does the same thing. You be the judge. The Forth source is from the ExampleForthCode page, but the comments (other than stack comments, which serve to identify input-output parameters) are removed. ---- '''Forth''' : star ( - ) [char] * emit ; : stars ( n - ) 0 do star loop cr ; : square ( n - ) dup 0 do dup stars loop drop ; : triangle ( n - ) 1 do i stars loop ; : tower ( n - ) dup triangle square ; : main ( - ) cr 7 stars cr 3 triangle cr 6 tower ; ---- '''C''' void stars(int n) { for (int i=0; i 0) putchar('*'); putchar('\n'); } void square(int n) { int i=n; while (i-- > 0) stars(n); } void triangle(int n) { int i=n; while (i-- > 0) stars(i); } void tower(int n) { triangle(n-1); square(n); } void main() { stars(7); triangle(3); tower(6); } ''Nice, but the triangle looks upside-down from the other versions.'' ---- To translate the above (incorrect) code back into Forth: : stars ( n -- ) begin dup while 1- [char] * emit repeat drop cr ; : square ( n -- ) dup begin dup while 1- over stars repeat 2drop ; : triangle ( n -- ) begin dup while dup stars 1- repeat drop ; : tower ( n -- ) dup 1- triangle square ; : main cr 7 stars 3 triangle 6 tower ; Note that many Forth dialects support an explicit counted loop form too, despite it not being ANSI-compliant: : square ( n -- ) dup for dup stars next drop ; To correct the triangle upside-down bug, : triangle ( n -- ) 1 begin 2dup >= while dup stars 1+ repeat 2drop ; : tower ( n -- ) dup 1- triangle square ; Also, if your coding conventions favor readability over conciseness, then a naive coder would ''really' write square as: : row ( n x -- n x ) over stars ; : square ( n -- ) dup begin dup while row 1- repeat 2drop ; A more experienced Forth coder would see the general pattern: begin dup while ... 1- repeat occur all over the place. So she can refactor the whole construct into a higher-order function: : asNecessary ( ... n xt -- ... ) >r begin dup while r@ execute 1- repeat drop r> drop ; : .* [char] * emit ; : stars ( n -- ) ['] .* asNecessary cr ; : row ( n x -- n x ) over stars ; : square ( n -- ) dup ['] row asNecessary drop ; : row ( n x -- n x ) swap dup stars 1+ swap ; ( hooray for HyperStaticGlobalEnvironment''''''s! ) : triangle ( n -- ) 0 swap ['] row asNecessary drop ; : tower ( n -- ) dup 1- triangle square ; : main cr 7 stars 3 triangle 6 tower ; If you're even more advanced, you can write words to permit code blocks right inside of Forth colon-definitions. We employ knowledge of immediate-words to extend the compiler, plus knowledge of run-time string evaluation to implement text-substitution macros. ( Add code quotations to GForth; odds are good it'll work elsewhere too. ) variable quotedCode : $( S" ahead [ :noname " evaluate ; immediate : $) S" ; quotedCode ! ] then [ quotedCode @ ] literal " evaluate ; immediate : stars $( [char] * emit $) asNecessary cr ; : square dup $( over stars $) asNecessary drop ; : triangle 1 swap $( swap dup stars 1+ swap $) asNecessary drop ; : tower dup 1- triangle square ; : main cr 7 stars 3 triangle 6 tower ; So, with only 2 lines of "blood, sweat, and tears", easily tucked away into a library, to define a new language feature, plus one higher-order function, the ''remainder'' of the program actually becomes ''substantially more'' readable and maintainable than any C version posted here to date. --SamuelFalvo ---- First of all, you really need to stop simulating DO/FOR loops with WHILE loops. Especially on a page demonstrating the readability of Forth. Secondly, while code quotations are awesome, I really don't think that this example is more readable with them. This code should be written like so (the standard words are in uppercase ''only'' for strict ANSI compliance): \ Just in case your system doesn't have FOR loops. [UNDEFINED] FOR [IF] : FOR 0 POSTPONE LITERAL POSTPONE DO ; IMMEDIATE SYNONYM NEXT LOOP [THEN] \ Also, asNeccesary is traditionally defined as : times ( i*x xt n -- j*x ) FOR DUP EXECUTE NEXT DROP ; : star [CHAR] * EMIT ; : stars ( n -- ) FOR star NEXT CR ; : square ( n -- ) DUP FOR DUP stars NEXT DROP ; : triangle ( n - ) 1 DO I stars LOOP ; : tower ( n -- ) DUP triangle square ; : go CR 7 stars 3 triangle 6 tower ; --- I'm new to Factor, but here's an attempt at a port : star ( -- ) "*" write ; : stars ( n -- ) [ star ] times nl ; : square ( n -- ) dup [ stars ] curry times ; : triangle ( n -- ) iota [ 1 + stars ] each ; : tower ( n -- ) [ triangle ] [ square ] bi ; : main ( -- ) nl 7 stars nl 3 triangle nl 6 tower ; ---- See also: ForthReadability ChuckMoore ---- CategoryForth