Sometimes I've found Forth code that is written without the Forth style. This page shows two examples, and how I rewrote them. This page is a brief version of the original article in Spanish, with step by step changes in the code.

Example 1

In Sideras (page in Spanish), a little game written in Ace Forth by an unknown author, I found the following word:


: izq
  x @ 0 > ascii 5 k= and
  if
    x c@ 1- x !
  then
;

The word k= has the following definition (but it's not relevant for the example);


: k=  inkey =  ;

The word izq (abbreviation of "left" in Spanish) tests the 5 key and, if the player's x coord is more than zero, it is decreased.

It works... But it's not the Forth's style. Here you are my alternative:


: izq  x dup @ ascii 5 k= - 0 max swap !  ;

Result:

original code new code
words 15 11
control structures 1 0
calculations 2 1
times the x variable is mentioned 3 1

In Ace Forth, the result of a boolean operation is 0 or 1. In ANS Forth the result is 0 or -1 (more useful and logical), so the code would be:


: izq  x dup @ [char] 5 k= + 0 max swap !  ;

Example 2

Let's see a larger example. The listing of Chase, a little game for the Jupiter Ace, was published by Andrew Curtis in Popular Computing Weekly in 1983.

Original code

The original code is almost ilegible:


10 VARIABLE X
15 VARIABLE Y
1 VARIABLE A
1 VARIABLE B

: CHASE CLS 10 X ! 15 Y ! 1 A ! 1 B ! BEGIN X @ Y @ AT ."  " A @ B @ AT ."  " INKEY 53 = IF Y @ 2 - Y ! THEN INKEY 54 = IF X @ 2 - X ! THEN INKEY 55 = IF X @ 2 + X ! THEN INKEY 56 = IF Y @ 2 + Y ! THEN X @ 20 > IF 20 X ! THEN Y @ 30 > IF 30 Y ! THEN X @ 1 < IF 1 X ! THEN Y @ 1 < IF 1 Y ! THEN X @ A @ = IF Y @ B @ = IF ." GOT YOU!" 250 1000 BEEP QUIT THEN THEN X @ A @ > IF A @ 1+ A ! THEN X @ A @ < IF A @ 1– A ! THEN Y @ B @ > IF B @ 1+ B ! THEN Y @ B @ < IF B @ 1– B ! THEN X @ Y @ AT ." A" A @ B @ AT ." E" 250 70 BEEP 0 1 = UNTIL ;

In lowercase and with proper indentation, the code looks much better. It's clear the code was written with the style of BASIC: many conditionals, and many redundant calculations.


10 variable x
15 variable y
1 variable a
1 variable b

: chase 
	cls 
	10 x ! 15 y ! 
	1 a ! 1 b ! 
	begin 
		x @ y @ at ."  "
		a @ b @ at ."  "
		inkey 53 = if y @ 2 - y ! then 
		inkey 54 = if x @ 2 - x ! then 
		inkey 55 = if x @ 2 + x ! then 
		inkey 56 = if y @ 2 + y ! then 
		x @ 20 > if 20 x ! then 
		y @ 30 > if 30 y ! then 
		x @ 1 < if 1 x ! then 
		y @ 1 < if 1 y ! then 
		x @ a @ = if 
			y @ b @ = if 
				." got you!" 250 1000 beep quit 
			then 
		then 
		x @ a @ > if a @ 1+ a ! then 
		x @ a @ < if a @ 1– a ! then 
		y @ b @ > if b @ 1+ b ! then 
		y @ b @ < if b @ 1– b ! then 
		x @ y @ at ." A" 
		a @ b @ at ." E" 
		250 70 beep	 
		0 1 = 
	until 
;

Modified code

This is my version, with no conditional structure, simplified calculations and simpler main loop:


10 variable x
15 variable y
1 variable a
1 variable b

: chase 
	cls 
	10 x ! 15 y ! 
	1 a ! 1 b ! 
	begin 
		x @ y @ at space
		a @ b @ at space
		y @ inkey 53 = 2 * - inkey 56 = 2 * + 1 max 30 min y !
		x @ inkey 54 = 2 * - inkey 55 = 2 * + 1 max 20 min x !
		x @ a @ = y @ b @ = and 0=
	while
		a @  x @ over > +  x @ a @ < negate +  a !
		b @  y @ over > +  y @ b @ < negate +  b !
		x @ y @ at ." A" 
		a @ b @ at ." E" 
		250 70 beep 
	repeat 
	." got you!" 250 1000 beep
;

It's almost Forth style, but not completely: Factoring is needed. Instead of one large word, many little specialized and independent words are better: the code gets easier to read and mantain.

The result of factoring the code of Chase became a new program: Heat Seeker.

URL: http://programandala.net/en.article.2009.06.24.forth_style

Page published in 2009-06-24 16:08 CEST
Last change made in 2010-01-25T13:24:02+01:00